用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;;
如果我们想做一些非常复杂的事情,比如打印一个int列表,该怎么办?使用此功能,您可以轻松地:print_int_list [3;6;78;5;2;34;7];;
打印(整数*字符串)列表(即整数和字符串对的列表): 或(* 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
因此,如果我想将浮动列表输出到csv文件,我可以使用以下命令:let float_list_to_csv_row input_list = string_of_list input_list string_of_float ","
(** 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的
格式规范(用于用户定义的打印)吗?我刚刚开始学习OCaml。我尝试了%d格式规范。事实上,我没有意识到“;”这允许指定多个语句,就像阿克的回答一样。我想补充一点,重写%a
似乎是一种耻辱。我同意这一点。但是理解列表是如何工作的仍然很有趣。第二行的空括号有什么意义?@Noah_S列表。iter
是类型()
的对象,我相信这是通常由函数返回的标准内容,仅用于副作用。其他打印功能,如unit
也有返回类型print\u int
。如果执行上面的单元
,您将看到let
将具有返回类型print\u list
。原则上可以返回其他内容,例如unit
,或42
,在这种情况下,返回类型将分别为“全部完成打印!”
或int
。由于print\u int是不推荐使用的列表。因此,使用printf的iter/List.map是更好的选择。有趣的是,唯一的“缺点”是总是有额外的string
代码>在列表中。例如,
我在函数[[4;2;];[2;];]
中添加了一个额外的分支,现在它非常完美:)如果您使用Core中的列表模块(例如,您正在跟踪真实世界的Ocaml),则需要执行:print_elements
是否确实需要添加“~f:”?@Anders是的,这是一个带标签的参数。如果遵循参数顺序,标签不是可选的吗?为什么不List.iter~f:(printf“%d”)a
List.iter print_int a代码>?应该是
@nnyby说应该是List.iter a print\u int
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 ","