[英]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.create
和Lazy.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.