簡體   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