【发布时间】:2013-08-23 23:05:20
【问题描述】:
在计算表达式上使用 Quote 成员将工作流转换为 AST,但希望在构造引用时不会在序列上实际调用 GetEnumerator()(即,具有某种形式的惰性)。在我的用例中,该序列表示一个远程数据源,并且在其上调用 GetEnumerator() 成员实际上会出去并针对它进行查询。
有什么方法可以隐式使用 Lazy 类型(并且仍然使用 Quote 成员) Source 成员,这样它就不会急切地调用
GetEnumerator(),而是有 只是还没有加载值?为什么将 let 绑定定义为模块的属性和另一个模块中的变量 函数在引用中被视为不同的实体,即
PropertyGetvsValue。
一些测试代码...
module Example
open Microsoft.FSharp.Quotations
[<Interface>]
type I<'Type> =
inherit seq<'Type>
type FooBuilder() =
member __.Source (x : #seq<'Type>) : I<'Type> = invalidOp "not implemented"
member __.For (source : I<'Type>, f : 'Type -> I<'Type>) : I<'Type> = invalidOp "not implemented"
member __.Zero () : I<'Type> = invalidOp "not implemented"
member __.Quote (expr : Expr<#seq<'Type>>) = expr
member __.Run (expr : Expr<#seq<'Type>>) =
System.Console.WriteLine(expr)
let foo = FooBuilder()
let bar = [1; 2; 3]
foo {
for x in bar do ()
}
let insideLet() =
let bar = [1; 2; 3]
foo {
for x in bar do ()
}
insideLet()
导致以下两个引用
Call (Some (Value (FSI_0009+FooBuilder)), For,
[Call (Some (Value (FSI_0009+FooBuilder)), Source,
[PropertyGet (None, bar, [])]),
Lambda (_arg1,
Let (x, _arg1,
Sequential (Value (<null>),
Call (Some (Value (FSI_0009+FooBuilder)), Zero,
[]))))])
Call (Some (Value (FSI_0009+FooBuilder)), For,
[Call (Some (Value (FSI_0009+FooBuilder)), Source, [Value ([1; 2; 3])]),
Lambda (_arg1,
Let (x, _arg1,
Sequential (Value (<null>),
Call (Some (Value (FSI_0009+FooBuilder)), Zero,
[]))))])
【问题讨论】:
标签: f# f#-3.0 computation-expression