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

上記の再帰値を持つサンプルコードは、次のF#コンパイラエラーを生成します。

エラーFS0432:[<ReflectedDefinition>]用語にプレフィックススプライス演算子'%'の使用を含めることはできません

上記のコードでスライシング演算子の使用法を確認できません。バグのようです...:)

これは、経由のみの見積もりの​​問題のようです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#コンパイラのバグかどうかということです。

4

1 に答える 1

5

これは、F#での再帰値の処理が原因である可能性があると思います。回避策として、再帰参照をパラメーターに変換できます。

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

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

即時再帰参照を作成しているため、最後の行はもちろん無効です(元のコードと同じように)が、それはあなたにアイデアを与えるはずです-実際には、おそらくxラムダ関数で囲みます。


編集 もともと問題は以下のようなものだと思っていましたが、今はわかりません(コメント参照)。

予期しないバグというよりは、(おそらく既知の)制限のように見えます。作成したコードの2つのバージョンには重要な違いがあります。最初のケースでは、名前付きのパブリック値(.NETに表示)をバインドしていますがx、2番目のケースでxは、引用符でのみ使用されるシンボルです。

アセンブリのメタデータに保存する必要がある見積もりは、次のようになります。

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

本文は引用符で囲まれxていますが、引用符で囲まれた記号ではないため、引用符につなぎ合わせる必要があります(つまり、評価され、結果が代わりに使用されます)。即時参照を使用して再帰値を宣言しているため、このコードは失敗することに注意してください。x定義の一部として評価する必要があるため、これは機能しません。

ただし、これはいくつかの実行時の側面を含むため、引用符で囲む%ことはできないと思います(つまり、上記をメタデータに格納することはできません) 。メタデータをロードするときに評価する必要があります。ReflectedDefinitionx

于 2010-05-30T15:39:55.763 に答える