在不知道嵌套内容何时结束的情况下正确缩进格式

Properly indenting with Format while not knowing when the nested content ends

我有一些调用其他函数的函数,我想打印嵌套调用以查看发生了什么。

让我们举这个最小的例子:

let a x = x + 1
let b x = x + 1

let f x =
  let res_a1 = a x in
  let res_b = b x in
  let res_a2 = a x in
  res_a1 + res_b + res_a2

let () = ignore (f 1)

为了打印正在发生的事情,我写了以下内容:

let a x =
  Format.printf "a@,";
  x + 1

let b x =
  Format.printf "b@,";
  x + 1

let f x =
  Format.printf "@[<v 2>[f@,";
  let res_a1 = a x in
  let res_b = b x in
  let res_a2 = a x in
  Format.printf "@]@,]@,";
  res_a1 + res_b + res_a2

let () =
  Format.printf "@[<v 0>";
  ignore (f 1);
  Format.printf "@."

问题是我需要添加一个额外的中断以正确缩进结束 ](在我的真实情况下,我不知道嵌套调用何时是最后一次调用,所以我不能只是不打印上次调用中的 @,):

[f
  a
  b
  a
  
]

如果我改写 Format.printf "@]]@,"; 那么我将不会有额外的休息时间,但结束 ] 将不会正确缩进:

[f
  a
  b
  a
  ]

有没有办法告诉 Format 正确缩进 ] 而无需添加额外的分隔符?

也就是说,我想要:

[f
  a
  b
  a
]

这是一个常见问题的示例,当您需要打印由分隔符穿插的对象列表时。如果你在每个元素之后添加一个分隔符,你将有一个丑陋的尾随分隔符。如果分隔符本身是换行符,它也会弄乱你的缩进。

常见的解决方案是对最后一个元素进行特殊处理,这在您的情况下不起作用。但是,对于您的情况,在每个元素之前添加一个分隔符是完全可以的。

let a x =
  Format.printf "@,a";
  x + 1

let b x =
  Format.printf "@,b";
  x + 1

let f x =
  Format.printf "[@[<v2>f";
  let res_a1 = a x in
  let res_b = b x in
  let res_a2 = a x in
  Format.printf "@]@,]";
  res_a1 + res_b + res_a2

let () =
  Format.printf "@.";
  Format.printf "@[<v0>";
  ignore (f 1);
  Format.printf "@]@."

这给了我们正确的,

[f
   a
   b
   a
]

请注意,您的代码缩进不正确的根本原因是您在上次调用中在 v2 框内发出了一个中断,因此它将始终以 +2 缩进。