1

我试图了解 OCamlFormat模块和语义标签的以下行为。

我的代码:

let prepare_ppf ppf =
  let original_stag_functions = Format.pp_get_formatter_stag_functions ppf () in
  let original_mark_tags_state = Format.pp_get_mark_tags ppf () in
  Format.pp_set_mark_tags ppf true;
  Format.pp_set_print_tags ppf false;
  Format.pp_set_formatter_stag_functions ppf {
    mark_open_stag = (fun stag ->
          print_endline "MARK-OPEN";
          match stag with
          | Format.String_tag s -> Printf.sprintf "<open:%s>" s
          | _ -> "<UNKNOWN>"
        );
    mark_close_stag = (fun stag ->
          print_endline "MARK-CLOSE";
          match stag with
          | Format.String_tag s -> Printf.sprintf "</close:%s>" s
          | _ -> "</UNKNOWN>"
        );
    print_open_stag = (fun _ -> print_endline "PRINT-OPEN"; ());
    print_close_stag = (fun _ -> print_endline "PRINT-CLOSE"; ());
  };
  print_endline "PREPARED";
  if Format.pp_get_mark_tags ppf () then print_endline "MARK:true";
  (fun ppf ->
      print_endline "RESET";
      Format.pp_set_mark_tags ppf original_mark_tags_state;
      Format.pp_set_formatter_stag_functions ppf original_stag_functions;)

let fprintf ppf fmt =
  let reset = prepare_ppf ppf in
  Format.kfprintf reset ppf fmt

let printf fmt = fprintf Format.std_formatter fmt

如果我将其粘贴到:utop 版本 2.8.0(使用 OCaml 版本 4.12.0)

当我运行它时:

utop # printf "@{<bold>%s@}" "hello";;
PREPARED
MARK:true
RESET
<bold>hello</bold>- : unit = ()

为什么mark_open_stag不调用和关闭函数?

如果我将第 5 行更改为Format.pp_set_print_tags ppf true;然后我看到print_open_stag调用了 and close 函数。

4

1 回答 1

5

这是标准输出格式化程序的缓冲和 utop 处理之间的交互。

可以看到缓冲问题

printf "@{<bold>%s@}" "A very very very very very very very very very very very very very very very very very long hello world";;

打印一半正确的

PREPARED
MARK:true
MARK-OPEN
<open:bold>A very very very very very very very very very very very very very very very very very long hello worldRESET
</bold>

更进一步,最后用

printf "@{<bold>%s@}@." "hello";;

产生正确的输出

PREPARED
MARK:true
MARK-OPEN
<open:bold>helloMARK-CLOSE
</close:bold>
RESET

问题是这样的

printf "@{<bold>%s@}" "hello"

完全缓冲其所有输入。它是 utop 牵手 stdout 格式化程序,它通过尝试打印来触发打印

- : unit = ()

这产生然后

<bold>hello</bold>- : unit = ()

因为在打印时utop已将格式化程序配置重置为自己的默认值。

于 2022-01-01T19:14:19.303 回答