我已经为一个模块实现了一台漂亮的打印机。目前我启动utop
,加载依赖项,然后#install_printer pp_custom;;
pp_custom
是漂亮的打印机。
我想自动化它,以便我可以以一种类似于lacaml
库的方式使用它,默认情况下"安装"矩阵的漂亮打印机。
我该怎么做呢?
简而言之,每当在顶部加载库时,都需要运行#install_printer
指令。我使用以下代码来评估顶层中的代码:
open Core_kernel.Std
open Or_error
let eval_exn str =
let lexbuf = Lexing.from_string str in
let phrase = !Toploop.parse_toplevel_phrase lexbuf in
Toploop.execute_phrase false Format.err_formatter phrase
let eval str = try_with (fun () -> eval_exn str)
这取决于 Core_kernel
,但您可以通过仅使用 eval_exn
而不是 eval
轻松摆脱这种情况(最后一个将可能的异常包装到 Or_error
monad 中(。获得eval
功能后,它可用于加载打印机:
let () = eval (sprintf "#install_printer %s;;" printer)
其中printer
是漂亮的打印函数的名称(通常使用模块名称限定(。通常,将此类代码放入名为 library.top
的单独库中,其中library
是库的名称。
为了进一步自动化,可以要求要在顶层自动打印的所有类型在中央注册表中注册自身,然后调用所有已注册的打印机,而不是手动枚举它们。要同时查看所有这些工作,您可以查看 BAP 库。它有一个名为 bap.top
的子库,可以自动安装所有打印机。每个希望可打印的类型都使用Printable.Make
函子实现Printable
签名,它不仅从基本定义中派生出许多打印函数,而且还在Core_kernel的Pretty_printer
注册表中注册生成的漂亮打印机(您可以使用自己的注册表,这只是一组字符串,仅此而已(。当bap.top
库加载到顶层(使用 require
或 load
指令(时,它会枚举所有已注册的打印机并安装它们。