マルセロの答えを完成させるために、はい、このタスクに引用を使用できます:
open Microsoft.FSharp.Quotations
open Microsoft.FSharp.Quotations.Patterns
let velocity = 5
let fn (e:Expr) =
match e with
| PropertyGet (e, pi, li) -> pi.Name
| _ -> failwith "not a let-bound value"
let name = fn <@velocity@>
printfn "%s" name
コードからわかるように、F# の let バインドされた最上位の定義値 (関数または変数) は、クラスのプロパティとして実装されます。
F# コードの一部を C# で機能的に書き換える方法を示すリンクが見つかりません。PropertyGet
コードを見ると、パターンが必要な理由が明らかになります。
式も評価したい場合は、プロジェクトにF# powerpackと参照をインストールする必要がありFSharp.PowerPack.Linq
ます。
クラスにEvalUntyped
メソッドを追加します。Expr
open Microsoft.FSharp.Linq.QuotationEvaluation
let velocity = 5
let fn (e:Expr) =
match e with
| PropertyGet (eo, pi, li) -> pi.Name, e.EvalUntyped
| _ -> failwith "not a let-bound value"
let name, value = fn <@velocity@>
printfn "%s %A" name value
インスタンスのメソッドに対してそれを行う必要がある場合は、次のようにします。
let velocity = 5
type Foo () =
member this.Bar (x:int) (y:single) = x * x + int y
let extractCallExprBody expr =
let rec aux (l, uexpr) =
match uexpr with
| Lambda (var, body) -> aux (var::l, body)
| _ -> uexpr
aux ([], expr)
let rec fn (e:Expr) =
match e with
| PropertyGet (e, pi, li) -> pi.Name
| Call (e, mi, li) -> mi.Name
| x -> extractCallExprBody x |> fn
| _ -> failwith "not a valid pattern"
let name = fn <@velocity@>
printfn "%s" name
let foo = new Foo()
let methodName = fn <@foo.Bar@>
printfn "%s" methodName
の使用法を示すコード スニペットに戻ると、タイプ セーフを保持する必要がある場合はEvalUntyped
、明示的な型パラメーターExpr
とダウンキャスト ( ) を追加できます。:?>
let fn (e:Expr<'T>) =
match e with
| PropertyGet (eo, pi, li) -> pi.Name, (e.EvalUntyped() :?> 'T)
| _ -> failwith "not a let-bound value"
let name, value = fn <@velocity@> //value has type int here
printfn "%s %d" name value