ocaml - 自动为递归数据结构生成差异 pp

标签 ocaml diff metaprogramming pretty-print

OUnit framework有一个功能assert_equal哪个可以(除其他外)进行论证 pp_diff以更易读的方式格式化两个输入的差异。由于数据结构在现实世界的应用程序中变得相当大,这似乎非常有用。

然而,手动实现它似乎也很乏味(特别是在开发过程中,当数据结构可能经常改变时)。所以我想知道是否有任何方法(最好是基于ppx的)来生成这样的函数?

如果 OCaml 中(还)没有这样的东西,那么在通常的嫌疑人(例如 Haskell、Lisp)中是否有任何相关的东西可以移植甚至只是用于灵感(因为我什至没有任何关于如何开始的线索)这样的实现)?换句话说:如何为相互递归的功能数据结构生成有意义的差异 pretty-print ?

最佳答案

将数据结构转换为人类可读形式(然后对该表示进行操作)的一种方法是使用 Core.Std s-表达式;它们基本上是在 LISP s 表达式和 Core.Std 之后建模的具有将数据从 s 表达式转换为 s 表达式的功能(以及用于自动化大多数无聊部分的语法扩展)。您可以在 Real World OCaml 的第 17 章中找到一个很好的概述。

对您的应用程序最重要的是,已经有计算 s 表达式之间差异的功能(您也可以漂亮地打印它们,然后对它们使用普通的文本差异)。此功能可以在 Core_extended.Std.Sexp.Diff 中找到.

例子:

open Core.Std                          (* basic Sexp functionality. *)
module XSexp = Core_extended.Std.Sexp  (* for Sexp diffs.           *)

type example = {
  a: string;
  b: int;
  c: float;
} with sexp (* syntax extension *)

let v1 = { a = "foo"; b = 1; c = 3.14 }
let v2 = { a = "bar"; b = 2; c = 3.14 }

let print_sexp s = print_endline (Sexp.to_string_hum s)

let sexp_diff s1 s2 =
  match XSexp.Diff.of_sexps ~original:s1 ~updated:s2 with
    None -> ""
  | Some(diff) -> XSexp.Diff.to_string diff

let main () =
  let s1 = sexp_of_example v1 in
  let s2 = sexp_of_example v2 in
  print_endline "=== first sexp ===";
  print_sexp s1;
  print_endline "=== second sexp ===";
  print_sexp s2;
  print_endline "=== print_diff output ===";
  XSexp.print_diff ~oc:stdout ~original:s1 ~updated:s2 ();
  print_endline "=== sexp_diff output ===";
  print_endline (sexp_diff s1 s2)

let () = main ()

在这里,print_diff是一个预定义的函数,用于将差异打印到 channel 和 sexp_diff是一个简单的自定义函数,它使用 Sexp.Diff以字符串形式返回差异。使用 corebuild -pkg core_extended example.native 构建程序后(或 .byte ,或使用 ocamlbuild 和必要的参数),运行程序应该产生以下输出:
=== first sexp ===
((a foo) (b 1) (c 3.14))
=== second sexp ===
((a bar) (b 2) (c 3.14))
=== print_diff output ===
 a
- foo
+ bar
 b
- 1
+ 2
=== sexp_diff output ===
 a
- foo
+ bar
 b
- 1
+ 2

关于ocaml - 自动为递归数据结构生成差异 pp,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34806521/

相关文章:

regex - OCaml 中 "not belonging to"的正则表达式

GIT:如何配置帅哥识别

macos - 3 个二进制文件的差异

syntax - Roslyn 语法树差异

formatting - 不在 sympy 的 `printing.ccode` 方法中将 X*X*X 收缩为 pow(X,3)

asynchronous - 使用 OCaml Async 并发写入

types - Ocaml 中 "type ...and "和 "let ...and "之间的范围不一致

ocaml - 如何请求变量的类型类?

C++ Boost::MPL fold 示例 - 参数数量错误

perl - 可以利用哪些现代(5.10 后)技巧来制作 Data::Dumper::Simple work-like work?