用OCaml打印列表

用OCaml打印列表,ocaml,Ocaml,我想做一些像这样简单的事情: 打印一份清单 let a = [1;2;3;4;5] 如何将此列表打印到标准输出?您可以通过简单的递归实现这一点: let rec print_list = function [] -> () | e::l -> print_int e ; print_string " " ; print_list l 打印列表的头部,然后在列表的尾部执行递归调用。您应该熟悉list.iter和list.map函数。它们对于在OCaml中编程是必不可少的。如果您也

我想做一些像这样简单的事情:

打印一份清单

let a = [1;2;3;4;5]

如何将此列表打印到标准输出?

您可以通过简单的递归实现这一点:

let rec print_list = function 
[] -> ()
| e::l -> print_int e ; print_string " " ; print_list l

打印列表的头部,然后在列表的尾部执行递归调用。

您应该熟悉list.iter和list.map函数。它们对于在OCaml中编程是必不可少的。如果您也熟悉Printf模块,那么您可以编写:

open Printf
let a = [1;2;3;4;5]
let () = List.iter (printf "%d ") a

我在大多数代码中打开Printf,因为我经常使用其中的函数。否则,您将不得不在最后一行中写入
Printf.Printf
。另外,如果您在toploop中工作,请不要忘记在上述语句的结尾使用双分号。

如果问题是找到实现此功能的最快方法,例如在调试时,那么我们可以说:

print_string (String.concat " " (List.map string_of_int list))
  • 扩展标准库(如电池)通常具有一些附加功能:

    List.print
      ~first:"[" ~sep:";" ~last:"]" (fun c x -> Printf.fprintf c "%d" x) stdout a
    
  • 我不久前写的这本小册子可以让你写:

    <:print<[$!i <- a${$d:i$}{;}]>>
    

    我很晚才回答,但还有一种方法:

    let print_list f lst =
      let rec print_elements = function
        | [] -> ()
        | h::t -> f h; print_string ";"; print_elements t
      in
      print_string "[";
      print_elements lst;
      print_string "]";;
    
    要打印整型列表,我们可以编写:

    print_list print_int [3;6;78;5;2;34;7];;
    
    但是,如果我们经常这样做,那么使用部分应用程序专门化函数将节省时间:

    let print_int_list = print_list print_int;;
    
    我们现在可以这样使用:

    print_int_list [3;6;78;5;2;34;7];;
    
    如果我们想做一些非常复杂的事情,比如打印一个int列表,该怎么办?使用此功能,您可以轻松地:

    (* Option 1 *)
    print_list (print_list print_int) [[3;6;78];[];[5];[2;34;7]];;
    
    (* Option 2 *)
    let print_int_list_list = print_list (print_list print_int);;
    print_int_list_list [[3;6;78];[];[5];[2;34;7]];;
    
    (* Option 3 *)
    let print_int_list_list = print_list print_int_list;;
    print_int_list_list [[3;6;78];[];[5];[2;34;7]];;
    
    打印(整数*字符串)列表(即整数和字符串对的列表):

    让sprintf_列表l=
    让acc=ref“{”在
    List.iteri(乐趣i x->
    acc:=!acc^
    如果我0
    然后Printf.sprintf“;%i”x
    else Printf.sprintf“%i”x
    )l;
    !acc^“}”
    让我们打印列表=
    让输出=sprintf_列表l输入
    Printf.fprintf标准输出“%s\n”
    
    我将按以下方式执行此操作:

    let a = [1;2;3;4;5];;
    List.iter print_int a;;
    

    仅包含%a的解决方案:

    open Printf
    let print_l outx l = 
         List.map string_of_int  l
      |> String.concat ";"
      |> fprintf outx "%s"
    
    测试:

    # printf "[%a]" print_l [1;2;3] ;;
    [1;2;3]- : unit = ()
    # printf "[%a]" print_l [];;
    []- : unit = ()
    

    实际上,您可以将打印列表和将列表转换为字符串解耦。这样做的主要优点是,您可以使用此方法在日志中显示列表,将它们导出到CSV

    我经常使用listHelper模块,具有以下功能:

    (** Generic method to print the elements of a list *)
    let string_of_list input_list string_of_element sep =
      let add a b = a^sep^(string_of_element b) in
      match input_list with
      | [] -> ""
      | h::t -> List.fold_left add (string_of_element h) t
    
    let float_list_to_csv_row input_list = string_of_list input_list string_of_float "," 
    
    因此,如果我想将浮动列表输出到csv文件,我可以使用以下命令:

    (** Generic method to print the elements of a list *)
    let string_of_list input_list string_of_element sep =
      let add a b = a^sep^(string_of_element b) in
      match input_list with
      | [] -> ""
      | h::t -> List.fold_left add (string_of_element h) t
    
    let float_list_to_csv_row input_list = string_of_list input_list string_of_float "," 
    

    你试了什么?您知道
    Printf.Printf的
    %a
    格式规范(用于用户定义的打印)吗?我刚刚开始学习OCaml。我尝试了%d格式规范。事实上,我没有意识到“;”这允许指定多个语句,就像阿克的回答一样。我想补充一点,重写
    列表。iter
    似乎是一种耻辱。我同意这一点。但是理解列表是如何工作的仍然很有趣。第二行的空括号有什么意义?@Noah_S
    ()
    是类型
    unit
    的对象,我相信这是通常由函数返回的标准内容,仅用于副作用。其他打印功能,如
    print\u int
    也有返回类型
    单元
    。如果执行上面的
    let
    ,您将看到
    print\u list
    将具有返回类型
    unit
    。原则上可以返回其他内容,例如
    42
    ,或
    “全部完成打印!”
    ,在这种情况下,返回类型将分别为
    int
    string
    。由于print\u int是不推荐使用的列表。因此,使用printf的iter/List.map是更好的选择。有趣的是,唯一的“缺点”是总是有额外的
    在列表中。例如,
    [[4;2;];[2;];]
    我在函数
    print_elements
    中添加了一个额外的分支,现在它非常完美:)如果您使用Core中的列表模块(例如,您正在跟踪真实世界的Ocaml),则需要执行:
    List.iter~f:(printf“%d”)a
    是否确实需要添加“~f:”?@Anders是的,这是一个带标签的参数。如果遵循参数顺序,标签不是可选的吗?为什么不
    List.iter print_int a?应该是
    List.iter a print\u int
    @nnyby说应该是
    List.iter print_int a哦,好的-我使用的是OCaml内核,它在这里切换了语法:内核中List.iter的类型是
    'at->f:('a->unit)->unit
    ,为了摆脱“标签被忽略”的警告,您可以这样做:
    List.iter a~f:print\u int
    
    let float_list_to_csv_row input_list = string_of_list input_list string_of_float ","