首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在OCaml中打印嵌套列表

在OCaml中打印嵌套列表
EN

Stack Overflow用户
提问于 2015-04-20 05:42:53
回答 2查看 798关注 0票数 0

我正致力于将一些Clojure代码移植到OCaml,并且遇到了以下问题:

代码语言:javascript
复制
let rotate ll =
    let cons x y = x :: y in
    let init = List.map (fun _ -> []) (List.hd ll) in
    let rres = List.fold_right (List.map2 cons) ll init in
    List.rev rres;;

let rec spiral_print matrix acc =
    match matrix with
    | [] -> acc
    | head :: tail -> spiral_print (rotate tail)  (acc @ head);;

不幸的是,这导致了以下情况:

代码语言:javascript
复制
utop # spiral_print [[1; 2; 3]; [8; 9; 4]; [7; 6; 5]] [];;
Exception: (Failure hd).

我想调试为什么会发生这种情况,但是当我打开跟踪时,我得到了如下结果:

代码语言:javascript
复制
#trace spiral_print;;
spiral_print [[1; 2; 3]; [8; 9; 4]; [7; 6; 5]] [];;
spiral_print <-- [[<poly>; <poly>; <poly>]; [<poly>; <poly>; <poly>]; [<poly>; <poly>; <poly>]]
spiral_print --> <fun>
spiral_print* <-- []
spiral_print <-- [[<poly>; <poly>]; [<poly>; <poly>]; [<poly>; <poly>]]
spiral_print --> <fun>
spiral_print* <-- [<poly>; <poly>; <poly>]
spiral_print <-- [[<poly>; <poly>]; [<poly>; <poly>]]
spiral_print --> <fun>
spiral_print* <-- [<poly>; <poly>; <poly>; <poly>; <poly>]
spiral_print <-- [[<poly>]; [<poly>]]
spiral_print --> <fun>
spiral_print* <-- [<poly>; <poly>; <poly>; <poly>; <poly>; <poly>; <poly>]
spiral_print <-- [[<poly>]]
spiral_print --> <fun>
spiral_print* <-- [<poly>; <poly>; <poly>; <poly>; <poly>; <poly>; <poly>; <poly>]
spiral_print* raises (Failure hd)
spiral_print* raises (Failure hd)
spiral_print* raises (Failure hd)
spiral_print* raises (Failure hd)
spiral_print* raises (Failure hd)
Exception: (Failure hd).

是否有一种方法可以检查单个函数执行的内部状态,以某种方式捕获bug?

我会用其他语言的打印或漂亮的打印。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2015-04-20 13:04:28

ocamldebug和toplevel将拒绝打印多态容器的元素,除非限制类型:

代码语言:javascript
复制
let int_spiral_print : int list list -> int list -> int list = spiral_print;;
val int_spiral_print : int list list -> int list -> int list = <fun>
# #trace int_spiral_print;;
int_spiral_print is now traced.
# int_spiral_print [[1; 2; 3]; [8; 9; 4]; [7; 6; 5]] [];;
int_spiral_print <-- [[1; 2; 3]; [8; 9; 4]; [7; 6; 5]]
int_spiral_print --> <fun>
...

但是在这里进行正常的回溯会更有效率。为了得到它,把你的代码放入一个文件,例如,

代码语言:javascript
复制
$ cat spiral_print.ml

let rotate ll =
  let cons x y = x :: y in
  let init = List.map (fun _ -> []) (List.hd ll) in
  let rres = List.fold_right (List.map2 cons) ll init in
  List.rev rres

let rec spiral_print matrix acc =
  match matrix with
  | [] -> acc
  | head :: tail -> spiral_print (rotate tail)  (acc @ head)

let _ =
  Printexc.record_backtrace true;
  spiral_print [[1; 2; 3]; [8; 9; 4]; [7; 6; 5]] []

注意,我添加了Printexc.record_backtrace true以启用通常禁用的回溯记录。您还可以使用环境变量:OCAMLRUNPARAM=b启用它。然后您可以编译和运行您的程序,以获得一个很好的回溯:

代码语言:javascript
复制
ocamlbuild spiral_print.d.byte --
Fatal error: exception Failure("hd")
Raised at file "pervasives.ml", line 30, characters 22-33
Called from file "spiral_print.ml", line 3, characters 36-48
Called from file "spiral_print.ml", line 10, characters 33-46
Called from file "spiral_print.ml", line 14, characters 2-51

一个合适的文本编辑器(又名emacs)甚至会为您突出显示异常的来源是(List.hd ll)

票数 2
EN

Stack Overflow用户

发布于 2015-04-20 05:53:49

我写了那个旋转代码:-)

如果您将一个空列表传递给它,该函数将失败。我想这是你的问题。这个错误来自于List.hd。如果列表是空的,你只需要决定你想要什么答案。答案可能是一个空的列表。

代码语言:javascript
复制
let rotate ll =
    if ll = [] then
        []
    else
        let cons x y = x :: y in
        let init = List.map (fun _ -> []) (List.hd ll) in
        let rres = List.fold_right (List.map2 cons) ll init in
        List.rev rres

或者可能是稍显时髦的:

代码语言:javascript
复制
let rotate = function
    | [] -> []
    | hd :: _ as ll -> 
        let cons x y = x :: y in
        let init = List.map (fun _ -> []) hd in
        let rres = List.fold_right (List.map2 cons) ll init in
        List.rev rres

但是要回答实际问题,可以在执行过程中使用ocamldebug调试检查值。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/29740043

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档