列表中的Ocaml理解?

use*_*818 11 ocaml

似乎Ocaml电池具有理解语法:http: //en.wikipedia.org/wiki/List_comprehension#OCaml

但是,我应该包含哪个模块来使用此语法?我已经open Batteries,但它不起作用.或者是否有一种更惯用的方式来做列表理解?我可以使用List.map和BatList.remove_if来实现类似的结果,但这不太优雅.

ivg*_*ivg 12

目前,OCaml中有两个提供列表理解的库,一个以前是OCaml Batteries的一部分,另一个是随camlp4一起提供的.两者都没有被广泛使用,我个人不建议您使用任何.

要使列表理解起作用,您需要更改语言的语法.这可以通过使用预处理器预处理程序(使用扩展语法编写)来完成camlp4.此外,列表理解不是OCaml社区中的一等公民,现代工具包也不能很好地支持它.虽然,您仍然可以轻松地在顶层玩它,为您所需要的,安装列表理解包:

opam install pa_comprehension 
Run Code Online (Sandbox Code Playgroud)

并使用以下指令将其加载到顶层:

# #use "topfind";;
# #camlp4o;;
# #require "pa_comprehension";;
# open Batteries;;
# [? 2 * x | x <- 0 -- max_int ; x * x > 3 ?];;
Run Code Online (Sandbox Code Playgroud)

但同样,我个人认为列表理解并不是构建代码的最佳方式.

生活没有理解力

您提供的示例可以使用core_kernel Sequence模块(电池的模拟Enum)表示

let f n =
  Sequence.(range 0 n |>
            filter ~f:(fun x -> x * x > 3) |>
            map ~f:(fun x -> x * 2))
Run Code Online (Sandbox Code Playgroud)

因此,a 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))
Run Code Online (Sandbox Code Playgroud)

您可能会注意到,此示例比列表理解需要更多代码.但是一旦你的程序开始从简单的整数hello world应用程序成熟到更复杂的东西,你就会同意使用显式迭代器更具可读性和可理解性.

此外,由于库中Core的库是如此一致,您可以使用简单List而不是Sequence仅使用前者替换后者.但是,当然,与之List不同的是热切,Sequence因此max_int使用列表并不是一个好主意.

此外,由于所有容器都是monad,因此可以使用monadic运算符进行映射,例如:

let odds n = List.(range 0 n >>| fun x -> x * 2 + 1)
Run Code Online (Sandbox Code Playgroud)

  • @ user69818:如果你有一个管道运算符定义了`|>`,那就不错了(参见http://www.ocamlpro.com/blog/2012/08/20/ocamlpro-and-4.00.0.html"管道运营商") (4认同)