遍历 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
,其中 se
是 List [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"
我正在尝试遍历 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
,其中 se
是 List [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"