ocaml printf function: skip formatting entirely if some condition holds

ocaml, printf

Solution

The continuation functions such as `Printf.kfprintf` are provided specifically to allow format wrappers such as this. It looks something like this:

open Printf

type log_level = Error | Warn | Info

let ord = function Error -> 50 | Warn  -> 40 | Info  -> 30

let string_of_lvl = function
  | Error -> "error"
  | Warn -> "warn"
  | Info -> "info"

let current_level = ref (ord Warn)

let printf_with_info name lvl =
  kfprintf fprintf stdout "[<%s>] <%s>: " name (string_of_lvl lvl)

let logf name lvl =
  if ord lvl >= !current_level then match lvl with
   | Error | Warn -> printf
   | Info -> printf_with_info name lvl
  else
    ifprintf stdout

Problem

(extracted from ocaml: exposing a printf function in an object's method, so it can be answered independently) I have the following (simplified) ocaml code, for a logger: ``` type log_level = | Error | Warn | Info let ord lvl = match lvl with | Error -> 50 | Warn -> 40 | Info -> 30 let current_level = ref (ord Warn) let logf name lvl = let do_log str = if (ord lvl) >= !current_level then print_endline str in Printf.ksprintf do_log ``` The logf function can be used with a printf format, as in: ``` logf "func" Warn "testing with string: %s and int: %d" "str" 42; ``` Is there any way to achieve the typical logging behaviour of only formatting arguments when they're actually needed? i.e something like: ``` let logf name lvl <args> = if (ord lvl) >= !current_level then Printf.printf <args> ``` I'm thinking it's because only the compiler knows how many arguments there will be in a format expression, and I guess there's no such thing as varargs in ocaml? So you can't ever define the full body of a printf function, you can only use currying and let the compiler magic figure it out. Is there any way to achieve what I want? Perhaps with `mkprintf`?

Original source