繁体   English   中英

这是F#引用错误吗?

[英]Is this an F# quotations bug?

[<ReflectedDefinition>]
let rec x = (fun() -> x + "abc") ()

具有上面的递归值的示例代码产生以下F#编译器错误:

错误FS0432:[<ReflectedDefinition>]术语不能包含前缀拼接运算符'%'的使用

我在上面的代码中看不到任何切片运算符的用法,看起来像个bug ... :)

看起来这是仅通过ReflectedDefinitionAttribute引用的问题,正常引用的效果很好:

let quotation =
    <@ let rec x = (fun() -> x + "abc") () in x @>

使用隐藏的Lazy.createLazy.force用法可产生预期的结果:

val quotation : Quotations.Expr<string> =
   LetRecursive
   ([(x, Lambda (unitVar,
        Application
        (Lambda (unitVar0,
            Call (None,
            String op_Addition[String,String,String](String, String),
            [Call (None,
                String Force[String](Lazy`1[System.String]), // `
                [x]), Value ("abc")])),
        Value (<null>)))),
   (x, Call (None, Lazy`1[String] Create[String](FSharpFunc`2[Unit,String]), [x])),
   (x, Call (None, String Force[String](Lazy`1[String]), [x]))], x) // `

所以问题是:这是F#编译器错误吗?

我认为这可能是由于F#中对递归值的处理所致。 解决方法是,可以将递归引用转换为参数:

[<ReflectedDefinition>] 
let foo x = (fun() -> x + "abc") ()

// To construct the recursive value, you'd write:
let rec x = foo x

最后一行当然是无效的(就像您的原始代码一样),因为您正在创建立即递归引用,但是它应该给您一个想法-实际上,您可能会将x括在lambda函数中。


编辑 本来,我认为问题可能如下,但现在不确定(请参阅评论)。

对我来说,它看起来更像是(可能是已知的)限制,而不是意外的错误。 您编写的代码的两个版本之间有一个重要的区别-在第一种情况下,您绑定了一个名为x的公共值(对.NET可见),而在第二种情况下, x只是仅在报价。

必须存储在程序集的元数据中的报价如下所示:

let rec x = <@ (fun() -> %x + "abc") () @>

正文用引号引起来,但x并非用引号引起来,因此需要将其拼接成引号(即,将对其进行求值并在其位置使用结果)。 请注意,此代码将失败,因为您要声明具有立即引用的递归值-需要将x作为其定义的一部分进行评估,因此这将行不通。

但是,我认为%不能出现在ReflectedDefinition引号中(也就是说,您不能将以上内容存储在元数据中),因为它涉及一些运行时方面-加载元数据时需要评估x

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM