7

F# では、可変数のパラメーターを受け入れる関数をどのようにカリー化しますか?

私はこのようなコードを持っています...(ログ機能は単なる例であり、正確な実装は重要ではありません)

let log (msg : string) =
    printfn "%s" msg

log "Sample"

コード全体で、sprintf 形式の文字列で呼び出されます。

log (sprintf "Test %s took %d seconds" "foo" 2.345)

ログ関数の sprintf 機能をカリー化したいので、次のようになります...

logger "Test %s took %d seconds" "foo" 2.345

私は次のようなものを試しました

let logger fmt ([<ParamArray>] args) =
    log (sprintf fmt args)

しかし、ParamArray 引数を sprintf 呼び出しに渡す方法がわかりません。

これはF#でどのように行われますか?

4

2 に答える 2

8
let log (s : string) = ()
let logger fmt = Printf.kprintf log fmt

logger "%d %s" 10 "123"
logger "%d %s %b" 10 "123" true
于 2012-06-21T19:53:40.520 に答える
6

printfF# における のような関数の動作は、ある意味で特別です。これらは、予期される引数が何であるかを指定するフォーマット文字列を取ります。as shown by desco を使用Printf.kprintfして、フォーマット文字列を受け取る独自の関数を定義できますが、フォーマット文字列の処理を変更することはできません。

C# のようなことをしたい場合params(引数の数は可変ですが、書式文字列には依存しません)、ParamArrayメンバーで属性を直接使用できます。

open System

type Foo = 
  static member Bar([<ParamArray>] arr:obj[]) =
    arr |> Seq.mapi (fun i v -> printfn "[%d]: %A" i v)

次に、Foo.Barフォーマット文字列なしで任意の数の引数を指定して呼び出すことができます。

Foo.Bar("hello", 1, 3.14)

これは文字列の書式設定にはあまり適していませんが、他の状況では役立つ場合があります。残念ながら、それはメンバーでのみ機能します(で定義された関数では機能しませんlet

于 2012-06-21T20:46:05.483 に答える