2017-02-07 12 views
1

FSharp関数を使用して動的関数に変換することは可能ですか?あるいは、これは今後のFSharpのようなものでしょうか?しかし、このアプローチは非常に脆いようだ:FSharpの動的関数呼び出し

let func (a:int) (b:int) : int = 
    a + b 

let dynamicFunc = FSharpFunc.ToDynamicFunc(func) 

let argumentList = [1; 2] 

let object = dynamicFunc argumentList 

let result = object :?> int 

は、あなたが現在バック(calling a F# function by nameこのような)標準反射に落下していることが表示されます。主に実際の保証はないので、カバーの下で何が起こっているのかを知る必要があります。

このようなものは、関数をラップして物事を動的に行うために使用できます。

let wrapFun (x:'f) : 'f = 

    let args = FSharp.Reflection.FSharpType.GetFunctionElements <| x.GetType() 

    let runner (any:obj list) : obj = 
     // Do extra things 
     FSharpFunc.DynamicInvoke x 

    FSharp.Reflection.FSharpValue.MakeFunction (typeof<'f>, runner) :?> 'f 
+5

もっと現実的なユースケースを教えてください。動的に処理する方法はいくつかありますが、エラーを導入するのが簡単になるため、可能な限り回避するのが一般的です。あなたの特定の例では、静的に知られている型を持つ 'func'関数があるので、動的に呼び出すことは役に立たないようです。 – kvb

+0

この場合、私はラップされた関数を呼び出すことで引数を収集し、実際に関数を呼び出すリモートマシンにそれらを送信するリモート呼び出しについて考えていました。 –

答えて

0

F#は動的呼び出し演算子をサポートしています。しかし、あなたはあなたを実装する必要があります。ここであなたが

よう Tupleなものとして渡す必要があるだろうのparamsのためとして

// Dynamically invoke 'Next' method of 'Random' type 
let o = box (new Random()) 
let a : int = o?Next(10) 

を次のようにそれを使用することができるだろうhttp://www.fssnip.net/2U/title/Dynamic-operator-using-Dynamic-Language-Runtime

// Reference C# implementation of dynamic operations 
#r "Microsoft.CSharp.dll" 
open System 
open System.Runtime.CompilerServices 
open Microsoft.CSharp.RuntimeBinder 

// Simple implementation of ? operator that works for instance 
// method calls that take a single argument and return some result 
let (?) (inst:obj) name (arg:'T) : 'R = 
    // TODO: For efficient implementation, consider caching of call sites 
    // Create dynamic call site for converting result to type 'R 
    let convertSite = 
    CallSite<Func<CallSite, Object, 'R>>.Create 
     (Binder.Convert(CSharpBinderFlags.None, typeof<'R>, null)) 

    // Create call site for performing call to method with the given 
    // name and a single parameter of type 'T 
    let callSite = 
    CallSite<Func<CallSite, Object, 'T, Object>>.Create 
     (Binder.InvokeMember 
     (CSharpBinderFlags.None, name, null, null, 
      [| CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null); 
      CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null) |])) 

    // Run the method call using second call site and then 
    // convert the result to the specified type using first call site 
    convertSite.Target.Invoke 
    (convertSite, callSite.Target.Invoke(callSite, inst, arg)) 

から採取されたサンプルの実装であります

target?method(param1, param2)これは、ターゲットメソッドがその引数をタプルとして処理することを意味するため、一部のパターンマッチングが関与する場合とされない場合があります。

関連する問題