2012-06-21 54 views
6

在F#中,你如何克服一個接受可變數量參數的函數?在F#中,你如何克服ParamArray函數(如sprintf)?

我有這樣的代碼...(日誌功能僅僅是一個例子,實際的實現並不重要)

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#中完成的?

+2

僅供參考 - 您正在詢問[格式化表達式](http://msdn.microsoft.com/zh-cn/library/ee340241) (這是鍵入),而不是參數數組(它是無類型的)。 – Daniel

回答

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

logger "%d %s" 10 "123" 
logger "%d %s %b" 10 "123" true 
+0

感謝這大致是我正在尋找 – Fendy

5

F#中類似printf函數的行爲在某種程度上是特殊的。他們採用格式字符串,它指定了期望的參數。如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定義的函數)一起工作