Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/.htaccess/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
引用计算表达式中的F#惰性_F#_F# 3.0_Computation Expression - Fatal编程技术网

引用计算表达式中的F#惰性

引用计算表达式中的F#惰性,f#,f#-3.0,computation-expression,F#,F# 3.0,Computation Expression,在计算表达式上使用Quote成员将工作流转换为AST,但希望在构造Quote时不会在序列上实际调用GetEnumerator()(即,具有某种形式的惰性)。在我的用例中,该序列表示一个远程数据源,调用该序列上的GetEnumerator()成员将实际执行查询 是否有某种方法可以隐式地在上使用Lazy类型(并且仍然使用Quote成员) 源成员,使其不急于调用GetEnumerator(),而是 只是还没有加载值 为什么let绑定定义为一个模块的属性和另一个模块中的变量 在报价单中被视为不同实体的函

在计算表达式上使用Quote成员将工作流转换为AST,但希望在构造Quote时不会在序列上实际调用
GetEnumerator()
(即,具有某种形式的惰性)。在我的用例中,该序列表示一个远程数据源,调用该序列上的
GetEnumerator()
成员将实际执行查询

  • 是否有某种方法可以隐式地在上使用Lazy类型(并且仍然使用Quote成员) 源成员,使其不急于调用
    GetEnumerator()
    ,而是 只是还没有加载值

  • 为什么let绑定定义为一个模块的属性和另一个模块中的变量 在报价单中被视为不同实体的函数,即
    PropertyGet
    vs

  • 一些测试代码

    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()
    
    模块示例
    打开Microsoft.FSharp.quotes
    []
    第一类
    类型FooBuilder()=
    成员来源(x:#seq=invalidOp“未实现”
    成员_uu.For(来源:I I=invalidOp“未实施”
    成员_uu.Zero():I>)=expr
    成员运行(expr:expr
    是否有某种方法可以隐式地在源成员上使用Lazy类型(并且仍然使用Quote成员),这样它就不会急切地调用GetEnumerator(),而只是还没有加载值

    我不认为有办法隐式使用Lazy类型。但是,我不太理解这个问题-当您使用
    Quote
    方法时,您可以对得到的引号执行任何转换,这样您就可以转换引号,使其不会实际调用
    GetEnumerator
    成员(当然,您必须用其他返回数据的东西替换它…)

    关键的一点是,构建查询不会调用
    GetEnumerator
    方法。因此,您应该能够在不调用
    GetEnumerator
    的情况下获取报价并对其进行转换和评估

    为什么let绑定被定义为一个模块的属性和另一个函数中的变量,在引号中被视为不同的实体,即
    PropertyGet
    vs
    Value

    模块中的let绑定被编译成静态成员,因此引号捕获对此静态成员的引用。对于局部变量,无法捕获引用,因此
    Value
    节点将数据直接嵌入引号中。(您可以编写一个转换,通过实际从属性获取当前值,将
    PropertyGet
    转换为
    Value

    EDIT:当我创建一个调用
    GetEnumerator
    时抛出的
    IEnumerable
    时,F#interactive中打印的引号显示错误(因为F#interactive试图计算序列以输出前几个成员),但引号仅包含源代码作为

    如果从构建器中删除
    Run
    方法(以便它只返回引号),那么这应该可以工作(并返回“fancy source”字符串):

    type FancySource()=
    成员x.Source=“花式来源”
    接口seq与
    成员x.GetEnumerator()=故障带“!”
    接口System.Collections.IEnumerable与
    成员x.GetEnumerator()=故障带“!”
    让insideLet()=
    let bar=new FancySource()
    foo{for x in bar do()}
    将insideLet()与
    |Patterns.Call(,,Patterns.Call(,,[Patterns.Value(:?FancySource as v,)]):::->
    v、 来源
    
    在对源代码的调用中,参数是一个包含值的单例列表。在我的示例中,它是列表[1;2;3],但在我的远程数据源中,它是结果的序列。因此
    GetEnumerator()
    以某种方式被内部调用以生成它。@user2712561我认为它实际上并没有调用
    GetEnumerator
    。请参见编辑。
    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,
                                          []))))])
    
    type FancySource() = 
      member x.Source = "fancy source"
      interface seq<int> with
        member x.GetEnumerator() = failwith "!" 
      interface System.Collections.IEnumerable with
        member x.GetEnumerator() = failwith "!" 
    
    let insideLet() =
      let bar = new FancySource()
      foo { for x in bar do () }
    
    match insideLet() with
    | Patterns.Call(_, _, Patterns.Call(_, _, [Patterns.Value(:? FancySource as v, _)])::_) -> 
        v.Source