3

関数の時間を測定したいのですが、最大 3 つのパラメーターを使用する関数もあります。現在、以下の同じコードを 3 つのバリエーションで使用しています。

let GetTime f (args : string) = 
    let sw = Stopwatch.StartNew()
    f (args)
    printfn "%s : %A" sw.Elapsed 

3つの機能をこれに置き換えたい。

let GetTime f ( args : 'T[]) =
    let sW = Stopwatch.StartNew()
    match args.Length with
    | 1 -> f args.[0]
    | 2 -> f (args.[0] args.[1])
    printfn "%A" sW.Elapsed
    ()

しかし、3つの関数を使用すると、型の不一致のエラーが発生します。関数をパラメーターとして送信し、このように使用することは可能ですか?

4

4 に答える 4

5

なぜこのようなことをしないのですか?

let getTime f =
    let sw = Stopwatch.StartNew()
    let result = f ()
    printfn "%A" sw.Elapsed
    result

f1f2、およびf3がそれぞれ 1、2、および 3 つの引数を取る 3 つの関数であると仮定すると、次のgetTimeように関数を使用できます。

getTime (fun () -> f1 "foo")
getTime (fun () -> f2 "foo" "bar")
getTime (fun () -> f3 "foo" "bar" "baz")

ただし、FSI でいくつかの関数の時間を計測する必要がある場合は、この機能が既に組み込まれています。次のように入力するだけです。

> #time;;

タイミングがオンになります。

于 2014-11-21T07:23:00.663 に答える
2

おそらく、メソッド グループを引数としてに渡し、メソッド グループGetTimeのどのオーバーロードを呼び出すかをコンパイラに決定させることを考えているでしょう。これは、.NET コンパイラでは不可能です。メソッド グループは、コンパイラや ReSharper などのツールによるコード分析に使用されますが、実行時に実際に存在するものではありません。

于 2014-11-21T03:56:31.367 に答える
2

次のように、関数が引数をタプル形式で受け取る場合:

let f1 (s: string, b: bool) =
    System.Threading.Thread.Sleep 1000
    s

let f2 (n: int, s:string, dt: System.DateTime) =
    System.Threading.Thread.Sleep 1000
    n+1

その後、実装は簡単になります。

let Timed f args =
    let sw = System.Diagnostics.Stopwatch.StartNew()
    let ret = f args
    printfn "Called with arguments %A, elapsed %A" args sw.Elapsed 
    ret

使用法:

f1
|> Timed // note, at this time we haven't yet applied any arguments
<| ("foo", true)
|> printfn "f1 done, returned %A"

f2
|> Timed
<| (42, "bar", DateTime.Now)
|> printfn "f2 done, returned %A"

ただし、関数が引数をカリー化された形式で受け取る場合は、次のようになります。

let f1Curried (s: string) (b: bool) =
    System.Threading.Thread.Sleep 1000
    s

let f2Curried (n: int) (s:string) (dt: System.DateTime) =
    System.Threading.Thread.Sleep 1000
    n+1

少しややこしくなります。アイデアは、引数を非カリー化することを目的とした標準演算子(<|)(<||)、およびを使用することです。(<|||)

let Timed2 op f args =
    let sw = System.Diagnostics.Stopwatch.StartNew()
    let ret = op f args
    printfn "Called with arguments %A, elapsed %A" args sw.Elapsed 
    ret

f1Curried
|> Timed2 (<||) // again, no arguments are passed yet
<| ("foo", true)
|> printfn "f1Curried done, returned %A"

f2Curried
|> Timed2 (<|||)
<| (42, "bar", DateTime.Now)
|> printfn "f2Curried done, returned %A"
于 2014-11-23T02:50:46.210 に答える