似乎Ocaml电池具有理解语法: http://en.wikipedia.org/wiki/List_comprehension#OCaml
但是,我应该包含哪个模块才能使用此语法?我已经open Batteries
,但它不起作用。或者是否有一种更惯用的方式来做列表理解?我可以使用List.map和BatList.remove_if来实现类似的结果,但这不太优雅。
答案 0 :(得分:12)
目前,OCaml中有两个提供列表理解的库,一个以前是OCaml Batteries的一部分,另一个是随camlp4一起提供的。两者都没有被广泛使用,我个人不建议您使用任何。
要使列表理解起作用,您需要更改语言的语法。这可以通过使用camlp4
预处理器以扩展语法编写的程序预处理来完成。此外,列表理解不是OCaml社区中的一等公民,现代工具包也不能很好地支持它。虽然,您仍然可以轻松地在顶层玩它,为您所需要的,安装列表理解包:
opam install pa_comprehension
并使用以下指令将其加载到顶层:
# #use "topfind";;
# #camlp4o;;
# #require "pa_comprehension";;
# open Batteries;;
# [? 2 * x | x <- 0 -- max_int ; x * x > 3 ?];;
但是,我个人认为列表理解并不是构建代码的最佳方式。
您提供的示例可以使用core_kernel
Sequence
模块(电池类似Enum
)表示
let f n =
Sequence.(range 0 n |>
filter ~f:(fun x -> x * x > 3) |>
map ~f:(fun x -> x * 2))
因此,filter |> map
是一种常见的习惯用法,存在filter_map
函数:
let f n =
Sequence.(range 0 n |>
filter_map ~f:(fun x ->
if x * x > 3 then Some (x * 2) else None))
你可能会注意到,这个例子比列表理解需要更多的代码。但是一旦你的程序开始从简单的整数hello world应用程序成熟到更复杂的东西,你就会同意使用显式迭代器更具可读性和可理解性。
此外,由于Core
中的库非常一致,您可以使用简单的List
代替Sequence
,只需用前者替换后者即可。但当然,与List
不同,Sequence
非常渴望,所以使用列表与max_int
一起玩并不是一个好主意。
此外,由于所有容器都是monad,因此可以使用monadic运算符进行映射,例如:
let odds n = List.(range 0 n >>| fun x -> x * 2 + 1)
答案 1 :(得分:1)
列表理解已包含在标准ocaml
中#require "camlp4.listcomprehension";;
[ x * x | x <- [ 1;2;3;4;5] ];;
- : int list = [1; 4; 9; 16; 25]