Automatically create pp difference for recursive data structures

The OUnit framework has a function assert_equalthat can (among other things) take an argument pp_diffthat formats the difference of the two inputs in a more readable way. Since data structures grow quite large in real applications, this seems very useful.

However, it seems very tedious to implement this manually (especially during development, when data structures can change frequently). So I wonder if there is any way (preferably ppx-based) to create such a function?

If in OCaml there is no such thing (is), is there something connected between ordinary suspects (for example, Haskell, Lisp) that can be ported or even simply used for inspiration (since I don’t even have the slightest tell me how to start such Implementation)? In other words: how to create a meaningful distinctive printer for mutually recursive functional data structures?

+4
source share
1 answer

( ) Core.Std s; LISP s- Core.Std s- ( ). 17 Real World OCaml.

, s- ( , diff). 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 - diff , sexp_diff - , Sexp.Diff 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
+3

Source: https://habr.com/ru/post/1624397/


All Articles