Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

F#: Composing sprintf with a string -> unit function to allow formatting

Tags:

printf

f#

There's information out there on how to do custom processing on a format and its parts. I want to do something a bit simpler, specifically, I want to do something to the effect of:

let writelog : string -> unit = ... // write the string to the log

let writelogf = sprintf >> writelog // write a formatted string to the log

I'm not too surprised that the compiler gets confused by this, but is there any way to get it to work?

like image 585
Rei Miyasaka Avatar asked Sep 01 '26 23:09

Rei Miyasaka


2 Answers

The simplest way to define your own function that takes a formatting string like printf is to use Printf.kprintf function. The first argument of kprintf is a function that is used to display the resulting string after formatting (so you can pass it your writelog function):

let writelog (s:string) = printfn "LOG: %s" s
let writelogf fmt = Printf.kprintf writelog fmt

The fmt parameter that is passed as a second argument is the special format string. This works better than jpalmer's solution, because if you specify some additional arguments, they will be directly passed to kprintf (so the number of arguments can depend on the formatting string).

You can write:

> writelogf "Hello";;
LOG: Hello

> writelogf "Hello %d" 42;;
LOG: Hello 42
like image 133
Tomas Petricek Avatar answered Sep 04 '26 18:09

Tomas Petricek


This works

> let writelog = fun (s:string) -> printfn "%s" s;;

val writelog : string -> unit

> let writelogf arg = sprintf arg >> writelog;;

val writelogf : Printf.StringFormat<('a -> string)> -> ('a -> unit)

> writelogf "hello %s" "world";;
hello world
val it : unit = ()
>

(session is from FSI)

key is in the extra argument to writelogf

like image 35
John Palmer Avatar answered Sep 04 '26 19:09

John Palmer