2011-02-09 5 views
4

F#引用でグリップを取得するのに数時間を費やしましたが、私はいくつかの道路ブロックに出くわしました。私の必要条件は、識別された共用体型から単純な関数(整数、+、 - 、/、*)を取り出し、最終的にCコードを生成するために使用される式ツリーを生成することです。私はこれが「直接」機能を持つ引用を使用して可能であることを知っています。F#引用 - 値によって表される関数呼び出しへの移動

私の問題は、式ツリーが "値"で終わっているように見えて、その値をどのようにトラバースするのかわかりません。

私の質問は これは実際にこの状況で可能かどうかですか?または検討する価値のある他のアプローチがありますか?

type FuncType = 
| A of (int -> int -> int) 
| B 
| C 

[<ReflectedDefinition>] 
let add x y = x + y 


let myFunc1 = A (fun x y -> x + y) 
let myFunc2 = A add 

let thefunc expr = 
    match expr with 
    | A(x) -> 
     <@ x @> 
    | _ -> 
     failwith "fail" 

printfn "%A" (thefunc myFunc1) // prints "Value (<fun:[email protected]>)" 
printfn "%A" (thefunc myFunc2) // prints "Value (<fun:[email protected]>)" 
printfn "%A" <@ fun x y -> x + y @> // generates usable expression tree 

答えて

7

の名言構文的を引用されたF#コードを表します。これは、<@ x @>のようなものを書くと、指定された値を引用していることを指定した場合、引用はちょうどValueケースを含むことを意味します。 (変数が引用の外に定義されている場合、変数は自動的に値に置き換えられます)。

あなただけの明示的<@ .. @>またはReflectedDefinitionとしてマークされていたと引用に名前で呼ばれる(例えば<@ add @>ではなく、例えば、let f = add in <@ f @>用)機能を使用して引用されたコードの引用を得ることができます。

スニペットが示唆していることを実行できるようにするには、FuncTypeに引用符を格納する必要があります(書いたラムダ関数も引用符で囲まれています)。次のようなものがあります。

type FuncType = 
    | A of Expr<int -> int -> int> 
    | B | C 

[<ReflectedDefinition>] 
let add x y = x + y 

let myFunc1 = A <@ fun x y -> x + y @> 
let myFunc2 = A <@ add @> 

let thefunc expr = 
    match expr with 
    | A(x) -> x 
    | _ -> failwith "fail" 

これは、ReflectedDefinitionとマークされた機能にも有効です。あなたのような何かを追加する必要がある関数の本体(あなたはパラメータのための関数の引数に置き換える必要がありますが、これはあなたにいくつかのアイデアを与える必要があります)を抽出するには:あなたの偉大な答えを

match expr with 
| Lambdas(_, body) -> 
    match body with 
    | Call(_, mi, _) when Expr.TryGetReflectedDefinition(mi) <> None -> 
     let func = Expr.TryGetReflectedDefinition(mi) 
     match func with 
     | Some(Lambdas(_, body)) -> 
      // 'body' is the quotation of the body 
     | _ -> failwith "Not supported function" 
    | _ -> failwith "Not supported function" 
| _ -> failwith "Not supported expression" 
+0

おかげで、それが持っています引用の理解の間隙の多くを埋めることができ、私に前進する道を与えてくれました。 – Jimmy

関連する問題