Ocaml 如何使用Janestreet Core定义自定义异常打印机?

Ocaml 如何使用Janestreet Core定义自定义异常打印机?,ocaml,core,Ocaml,Core,默认情况下,故障异常被打印如下: # print_endline (Printexc.to_string (Failure "uh\noh"));; Failure("uh\noh") 为了提高可读性,我们希望按原样打印Failure的参数,因为我们知道它应该是人类可读的。在OCaml标准库中,我们将使用以下命令初始化应用程序: # Printexc.register_printer (function | Failure s -> Some ("Failure: " ^ s)

默认情况下,
故障
异常被打印如下:

# print_endline (Printexc.to_string (Failure "uh\noh"));;
Failure("uh\noh")
为了提高可读性,我们希望按原样打印
Failure
的参数,因为我们知道它应该是人类可读的。在OCaml标准库中,我们将使用以下命令初始化应用程序:

# Printexc.register_printer (function
  | Failure s -> Some ("Failure: " ^ s)
  | _ -> None
);;
Uncaught exception: Failure:
  Uncaught exception in subprocess 1234: Failure:
    something happened
    trace line 1
    trace line 2
  trace line 1
  trace line 2
  trace line 3
Printexc.to_string
的新行为是:

# print_endline (Printexc.to_string (Failure "uh\noh"));;
Failure: uh
oh
太好了。现在,如果我们使用core_内核库,首先我们可以看到,打印异常略有不同,但对人类读者来说并不更好:

#require "core_kernel";;
# print_endline (Printexc.to_string (Failure "uh\noh"));;
(Failure  "uh\
         \noh")
也许我们可以推翻这个?让我们试试看

# Printexc.register_printer (function
  | Failure s -> Some ("Failure: " ^ s)
  | _ -> None
);;
# print_endline (Printexc.to_string (Failure "uh\noh"));;
Failure: uh
oh
这是可行的,但它不使用属于
Core\u内核的打印机。如果我们使用它,我们仍然会得到同样的不可读结果:

# print_endline (Core_kernel.Exn.to_string (Failure "uh\noh"));;
(Failure  "uh\
         \noh")
Core\u kernel.Exn
不提供
register\u打印机
功能。因此,它看起来像是
Core\u kernel.Exn
确保我们不定义自定义异常打印机。有没有其他方法或者我们不应该使用
Core\u kernel.Exn
那么如果我们想显示人类可读的错误消息呢

编辑:对于上下文,我们最初的问题是很好地打印嵌套的错误消息。例如,我们想阅读如下内容:

# Printexc.register_printer (function
  | Failure s -> Some ("Failure: " ^ s)
  | _ -> None
);;
Uncaught exception: Failure:
  Uncaught exception in subprocess 1234: Failure:
    something happened
    trace line 1
    trace line 2
  trace line 1
  trace line 2
  trace line 3
我们使用缩进来引用和转义,而不是双引号和反斜杠转义序列。

Base.Exn
(其中
Core\u kernel.Exn
是别名)使用Sexplib0打印机和转换器将错误打印为人类可读的s表达式。可以为异常添加自定义sexp转换器
Sexplib0.Exn\u converter.add

但是,如果您不打算将异常打印为s表达式,我认为确实没有理由使用
Base.Exn
的打印机

编辑:由于问题似乎是S表达式的打印,一种解决方案可能是使用Base.Exn.sexp_of,然后插入自定义S表达式打印机,该打印机不转义字符串,也不打印括号:

let pp_sep ppf () = Format.fprintf ppf "@ "
let pp_sexp ppf = function
  | Atom s -> Format.pp_print_string ppf s
  | List l ->
    Format.fprintf ppf "@[<v 2>  %a@]" 
      (Format.pp_print_list ~pp_sep pp_sexp) l

let to_string exn = Format.asprintf "%a" pp_sexp (Exn.sexp_of_t exn)
让pp_sep ppf()=Format.fprintf ppf“@”
设pp_sexp ppf=函数
|Atom s->Format.pp\u print\u string ppf s
|列表l->
Format.fprintf ppf“@[%a@”
(Format.pp_print_list~pp_sep pp_sexp)l
let to_string exn=Format.asprintf“%a”pp_sexp(exn.sexp\u of_t exn)

我明白了。不幸的是,一旦出现嵌套的异常,例如
到_string(Failure(to _stringe))
,S表达式就不再是人类可读的。将此添加为示例。