In F#, how do you curry ParamArray functions (like sprintf)?
Asked Answered
T

2

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#?

Turnbow answered 21/6, 2012 at 19:47 Comment(1)
FYI - You're asking about formatting expressions (which are typed), not param arrays (which are untyped).Gil
S
8
let log (s : string) = ()
let logger fmt = Printf.kprintf log fmt

logger "%d %s" 10 "123"
logger "%d %s %b" 10 "123" true
Supercargo answered 21/6, 2012 at 19:53 Comment(1)
Thanks this is roughly what I was looking forTurnbow
P
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)

Paction answered 21/6, 2012 at 20:46 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.