【问题标题】:Printing nested lists in OCaml在 OCaml 中打印嵌套列表
【发布时间】:2015-04-20 05:42:53
【问题描述】:

我正在将我的一些 Clojure 代码移植到 OCaml,但遇到了以下问题:

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);;

不幸的是,这会导致以下结果:

utop # spiral_print [[1; 2; 3]; [8; 9; 4]; [7; 6; 5]] [];;
Exception: (Failure hd).

我想调试为什么会发生这种情况,但是当我打开跟踪时,这就是我得到的:

#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).

有没有办法以某种方式检查各个函数执行的内部状态以捕捉错误?

我会在其他语言中使用 print 或 pretty print。

【问题讨论】:

    标签: printf ocaml


    【解决方案1】:

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

    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>
    ...
    

    但是这里有一个正常的回溯会更有效率。要获取它,请将您的代码放入文件中,例如,

    $ 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。然后你可以编译并运行你的程序,得到一个很好的回溯:

    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】:

      我写了旋转代码:-)

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

      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
      

      或者稍微时髦一点:

      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 在执行期间检查值。

      【讨论】:

      • 是的,先生,你做到了!我也在阅读您在 iOS 业务中的其他代码。谢谢你的分享,我已经从你那里学到了很多。 :)
      • 您在这里建议的更改也解决了问题。
      猜你喜欢
      • 2012-11-26
      • 1970-01-01
      • 2015-08-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-03-10
      • 1970-01-01
      相关资源
      最近更新 更多