遍历 OCaml 中的嵌套列表数据类型

Iterate through nested list data type in OCaml

我正在尝试遍历 Jane Street Sexplib module 中定义的 Sexp.t 数据类型。我想以一种显示其递归结构以进行调试的方式打印出数据类型。到目前为止,这就是我所拥有的:

type sexp =
  | Atom of string
  | List of sexp list

(* pretty prints an sexp *)
let rec to_str (se : sexp) : string =
  match se with
  | Atom s -> s
  | List [] -> ""
  | List (hd :: tl) -> to_str hd ^ to_str (List tl)

let () =
  let se = List [Atom "a"; List [Atom "b"; Atom "c"]; Atom "d"; Atom "e"] in
  print_endline (to_str se)

输出是 abcde,一个扁平化的列表。我希望将其打印成类似于:

List [Atom "a"; List [Atom "b"; Atom "c"]; Atom "d"; Atom "e"]

我做了几次尝试,但很快就搞砸了。我只是不确定递归情况应该是什么样子。有人可以帮我吗?

这不是很有效,但对您的功能所做的更改很少,并且应该易于理解:

let rec to_str (se : sexp) : string =
  match se with
  | Atom s -> Printf.sprintf "Atom \"%s\"" s
  | List [] -> ""
  | List items ->
    let items = items |> List.map to_str |> String.concat "; " in
    Printf.sprintf "List [%s]" items

打印

List [Atom "a"; List [Atom "b"; Atom "c"]; Atom "d"; Atom "e"]

为方便起见,它使用 Printf.sprintf,但如果您愿意,仍然可以使用纯字符串连接。更高效的版本可以使用 Format.fprintf 代替。

@glennsl 提供的答案很好,但让我们看看您的代码在做什么,看看为什么它会为您提供所看到的结果。

let rec to_str (se : sexp) : string =
  match se with
  | Atom s -> s
  | List [] -> ""
  | List (hd :: tl) -> to_str hd ^ to_str (List tl)

然后您评估了 to_str se,其中 seList [Atom "a"; List [Atom "b"; Atom "c"]; Atom "d"; Atom "e"]

to_str (List [Atom "a"; List [Atom "b"; Atom "c"]; Atom "d"; Atom "e"])

to_str (Atom "a") ^ to_str (List [List [Atom "b"; Atom "c"]; Atom "d"; Atom "e"])

"a" ^ (to_str (List [Atom "b"; Atom "c"]) ^ to_str (List [Atom "d"; Atom "e"]))

"a" ^ (to_str (Atom "b") ^ to_str (List [Atom "c"]))
    ^ (to_str (Atom "d") ^ to_str (List [Atom "e"]))

"a" ^ ("b" ^ (to_str (Atom "c") ^ to_str (List [])))
    ^ ("d" ^ (to_str (Atom "e") ^ to_str (List [])))

"a" ^ ("b" ^ ("c" ^ ""))
    ^ ("d" ^ ("e" ^ ""))

"a" ^ ("b" ^ "c") ^ ("d" ^ "e")

"a" ^ "bc" ^ "de"

"abcde"