7

In F#, how do you curry a function that accepts a variable number of parameters?

I have code like this...(the log function is just an example, the exact implementation doesn't matter)

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

log "Sample"

It gets called throughout the code with sprintf formatted strings, ex.

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

I want to curry the sprintf functionality in the log function so it looks like...

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

I've tried something like

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

but I cannot figure out how to pass the ParamArray argument through to the sprintf call.

How is this done in F#?

Fendy
  • 73
  • 3
  • 2
    FYI - You're asking about [formatting expressions](http://msdn.microsoft.com/en-us/library/ee340241) (which are typed), not param arrays (which are untyped). – Daniel Jun 21 '12 at 20:00

2 Answers2

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

logger "%d %s" 10 "123"
logger "%d %s %b" 10 "123" true
desco
  • 16,642
  • 1
  • 45
  • 56
6

The behaviour of printf-like functions in F# is in some way special. They take a format string, which specifies what the expected arguments are. You can use Printf.kprintf as shown by desco to define your own function that takes a format string, but you cannot change the handling of format strings.

If you want to do something like C# params (where the number of arguments is variable, but does not depend on the format string), then you can use ParamArray attribute directly on a member:

open System

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

Then you can call Foo.Bar with any number of arguments without format string:

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

This is less elegant for string formatting, but it might be useful in other situations. Unfortunatelly, it will only work with members (and not with functions defined with let)

Tomas Petricek
  • 240,744
  • 19
  • 378
  • 553