7

在 F# 中,如何对接受可变数量参数的函数进行柯里化?

我有这样的代码......(日志功能只是一个例子,确切的实现并不重要)

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

log "Sample"

它在整个代码中使用 sprintf 格式的字符串被调用,例如。

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

我想在 log 函数中 curry 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

F#中 -like 函数的行为printf在某种程度上是特殊的。它们采用格式字符串,指定预期的参数是什么。您可以使用Printf.kprintfdesco 所示的方法来定义您自己的采用格式字符串的函数,但您不能更改格式字符串的处理方式。

如果你想做类似 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 回答