在F#,你怎么讨好的ParamArray功能(如sprintf的)?(In F#, how do y

2019-07-30 02:13发布

在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)

但我无法弄清楚如何通过对sprintf的调用传递的ParamArray参数。

这是如何在F#中做了什么?

Answer 1:

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

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


Answer 2:

的行为printf样的功能在F#是在某些方面特殊。 他们采取一个格式字符串,它指定了预期的论点是什么。 您可以使用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



文章来源: In F#, how do you curry ParamArray functions (like sprintf)?