在计算表达式上使用 Quote 成员将工作流转换为 AST,但希望它GetEnumerator()
不会在构造引用时在序列上实际调用(即,具有某种形式的惰性)。在我的用例中,序列代表一个远程数据源,调用它的GetEnumerator()
成员实际上会出去并查询它。
有没有办法在 Source 成员上隐式使用 Lazy 类型(并且仍然使用 Quote 成员),这样它就不会急切地调用
GetEnumerator()
,而是根本没有加载值?为什么将 let 绑定定义为模块的属性和另一个函数中的变量在引号中被视为不同的实体,即
PropertyGet
vsValue
。
一些测试代码...
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,
[]))))])