It seems that Ocaml batteries have comprehension syntax: http://en.wikipedia.org/wiki/List_comprehension#OCaml
However, what module should I include to use this syntax? I already open Batteries
, but it doesn't work. Or is there a more idiomatic way to do list comprehension? I can use List.map and BatList.remove_if to achieve similar results, but that is much less elegant.
Currently there're two libraries in OCaml that provide list comprehension, one was formerly a part of OCaml Batteries, another is shipped with camlp4. Neither is widely used and I, personally, do no recommend you to use any.
For list comprehension to work, you need to change the syntax of the language. This can be done with preprocessing your program, written in an extended syntax, with a camlp4
preprocessor. Also, list comprehension is not a first class citizen in OCaml community, and it is not well supported by the modern toolkits. Although, you can still easily play with it in a toplevel, for that you need, to install the list comprehension package:
opam install pa_comprehension
and load it into a toplevel, using the following directives:
# #use "topfind";;
# #camlp4o;;
# #require "pa_comprehension";;
# open Batteries;;
# [? 2 * x | x <- 0 -- max_int ; x * x > 3 ?];;
But again, my personal opinion that list comprehension is not the best way to structure your code.
The example, you provided, can be expressed using core_kernel
Sequence
module (an analog of the Batteries Enum
)
let f n =
Sequence.(range 0 n |>
filter ~f:(fun x -> x * x > 3) |>
map ~f:(fun x -> x * 2))
Hence a filter |> map
is such a common idiom there exists a filter_map
function:
let f n =
Sequence.(range 0 n |>
filter_map ~f:(fun x ->
if x * x > 3 then Some (x * 2) else None))
You may notice, that this examples takes more code, than list comprehension. But as soon as your programs will start to mature from simple hello world applications with integers to something more sophisticated, you will agree that using explicit iterators is more readable and comprehensible.
Also, since libraries in Core
are so consistent, you can use a simple List
instead of Sequence
just by substituting the latter by the former. But of course, List
is eager, unlike the Sequence
, so playing with max_int
using lists is not a good idea.
Moreover, since all containers are monads, you can use monadic operators for mapping, like:
let odds n = List.(range 0 n >>| fun x -> x * 2 + 1)
list comprehension is already included in standard ocaml
#require "camlp4.listcomprehension";;
[ x * x | x <- [ 1;2;3;4;5] ];;
- : int list = [1; 4; 9; 16; 25]
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With