什么时候在F#中支持无类型的打字报价?

时间:2012-05-17 17:57:10

标签: types f# programming-languages metaprogramming quotations

F#有类型和无类型的代码引用,我想知道哪一个会选择一个而不是另一个呢?

区别只是方便和无类型,并且键入的引用在所有情况下都可以转换为每个或者是键入的引用e。 G。使用无类型引用可能的子集?

是否有任何示例仅适用于打字,但不适用于无类型报价 - 或者反过来?

2 个答案:

答案 0 :(得分:7)

一般情况下,我建议您尽可能使用打字报价。像往常一样,这些类型将允许您静态地强制执行某些可能导致运行时失败的正确性条件。考虑:

let one = <@@ "one" @@>
// exception at runtime
let two = <@@ 1 + %%one @@>

而不是

let one = <@ "one" @>
// compile time error: the type 'string' does not match the type 'int'
let two = <@ 1 + %one @>

此外,有时无类型引用需要额外的类型注释,如果键入的引用不包括:

// ok
let l = <@ [1] @>
let l2 = <@ List.map id %l @>

// fails at runtime (obj list assumed instead of int list)
let l = <@@ [1] @@>
let l2 = <@@ List.map id %%l @@>

// ok
let l = <@@ [1] @@>
let l2 = <@@ List.map (id:int->int) %%l @@>

但是,如果您在引用之外构建非常通用的内容,则可能无法使用类型化引用(例如,因为类型不是静态知道的)。从这个意义上说,无类型的引用会给你更大的灵活性。

另请注意,根据需要在类型化和非类型化报价之间进行转换非常容易(从Expr<_>转换为Expr从输入转换为无类型;使用Expr.Cast转到其他方式)。

答案 1 :(得分:3)

通常,报价处理库的使用者将使用键入的引用。而引用处理作者需要使用无类型引用。

也就是说,您不会经常使用(<@@ @@>)运算符直接创建无类型引用。但是,为了使用各种F#核心库活动模式(例如Quotations.Patterns模块)递归处理引用,您可以使用非类型化形式的引用。

请注意,Expr<'T>扩展了Expr,并没有真正为其添加太多信息。也就是说,键入的引用实际上只是一种幻觉,所有捕获的元数据都在Expr对象中,并且仅在运行时可用。