ocaml:在对象的方法中公开printf函数

时间:2013-12-05 21:46:34

标签: generics types printf ocaml

对于记录器,我有以下(简化的)ocaml代码:

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

logf函数可以与printf格式一起使用,如:

logf "func" Warn "testing with string: %s and int: %d" "str" 42;

1)如何将其包装在一个对象中,以便绑定name我试过了:

class logger (name:string) =
    object (self)
        method logf lvl = logf name lvl
    end

(我的真正的记录器有更多的方法,所以它不像它在这里看起来那么毫无意义。而且,name根据格式化程序打印,即使我没有在此处包含该代码)< / p>

但我明白了:

The method logf has type
  log_level -> ('a, unit, string, unit) format4 -> 'a
where 'a is unbound

这似乎是合理的,知道我对format4类型的了解 - 它不知道它将接收什么输入。但是为什么上面的免费功能怎么样呢?我的猜测是编译器能够以某种方式专门化这个抽象/未绑定类型,无论它在函数的情况下使用它,但不是在类的情况下?

编辑:我将第(2)部分移至ocaml printf function: skip formatting entirely if some condition holds,以便可以独立回答

1 个答案:

答案 0 :(得分:2)

对于(1),您可以使用:

class logger (name: string) =
    object (self)
    method logf : 'a. log_level -> ('a, unit, string, unit) format4 -> 'a =
        fun lvl -> logf name lvl
    end

额外的语法创建了一种所谓的多态方法。

这是一个显示它有效的会话:

$ ocaml
        OCaml version 4.00.1

# #use "opf.ml";;
type log_level = Error | Warn | Info
val ord : log_level -> int = <fun>
val current_level : int ref = {contents = 40}
val logf : 'a -> log_level -> ('b, unit, string, unit) format4 -> 'b = <fun>
class logger :
  string ->
  object
    method logf : log_level -> ('a, unit, string, unit) format4 -> 'a
  end
# let l = new logger "name";;
val l : logger = <obj>
# l#logf Warn "Testing with %d %s" 88 "maybe";;
Testing with 88 maybe
- : unit = ()
#

对于(2),我认为事情已经按照您的意愿运作了。如果级别太低,则不会进行格式化。