Comprehension for OCaml
Comprehension for OCaml is a small syntax extension for OCaml 3.10, developed using Camlp4. The latest release is version 0.1.1, released December 18, 2007, which you may find here.
This extension adds or improves support for list comprehension, array comprehension, stream comprehension, lazy list comprehension and string comprehension inside OCaml. It may be used with either the revised syntax or the original syntax.
Comments, suggestions and bug reports are welcome.
Last Updates
12/18/2007
Fixed error in the documentation.
Syntax extensions
Examples in the original syntax may be found here. Examples in the revised syntax may be found here.
List comprehension
As in standard syntax, lists may be written
[] (*The empty list*)
[1] (*The list containing 1*)
[1;2] (*The list containing 1 and 2*)
plus, in the original syntax
1 :: [2;3;4](*The list containing 1, 2, 3 and 4*)
or, in the revised syntax
[1;2::[3;4]](*The list containing 1, 2, 3 and 4*)
With this extension, list ranges may now be written
[1 .. 20]
let a = 1 and b = 20 in [a .. b]
[0;1;2..18;19;20]
All these expressions produce the list of integers between 1 and 20. These lists are computed at run-time.
- This feature requires module MoreList, included in this distribution as source file moreList.ml .
As in the revised syntax, list comprehension loops may be written
[ i+1 | i <- [1;2;3;4;5] ] (*The list [2;3;4;5;6] *)
[ i+1 | i <- [1;2;3;4;5] ; i mod 2 = 0] (*The list [3;5] *)
[(i,j)| i <- [1;2] ; j <- [3;4]] (*The list [(1,3);(1,4);(2,3);(2,4)] *)
In addition, list comprehension loops may now be read from other data structures
[ i | (MoreString) i <- "aeiou" ] (*The list ['a';'e';'i';'o';'u'] *)
- This feature works with any module containing functions
map,filter,flatten,map_filterandto_listwith types similar to those of the corresponding functions in module MoreArray. A few modules are included with the necessary functions for lists, arrays, lazy lists strings and streams.
Array comprehension
As in the revised syntax, arrays may be written
[||] (*The empty array*)
[|1|] (*The array containing 1*)
[|1;2|] (*The array containing 1 and 2*)
With this extension, array ranges may now be written
[|1 .. 20|]
[|0;1;2..18;19;20|]
let a = 1 and b = 20 in [|a .. b|]
[|(0+1)..19;20|]
All these expressions produce the array of integers between 1 and 20. The first and second cases
are computed at compile-time, without array concatenations, while the third and fourth cases and
anything more complex need run-time computation. The fourth case additionally requires run-time
concatenations.
- This feature requires module MoreArray, included in this distribution as source file moreList.ml .
As for lists, array comprehension loops may be written
[| i+1 | i <- [|1;2;3;4;5|] |] (*The array [|2;3;4;5;6|] *)
[| i+1 | i <- [|1;2;3;4;5|] ; i mod 2 = 0|] (*The array [|3;5|] *)
[|(i,j)| i <- [|1;2|] ; j <- [|3;4|] |] (*The array [|(1,3);(1,4);(2,3);(2,4)|] *)
In addition, array comprehension loops may now be read from other data structures
(”cross-comprehension”)
[| i | (MoreString) i <- "aeiou" |] (*The array [|'a';'e';'i';'o';'u'|] *)
- This feature works with any module containing functions
map,filter,flatten,map_filterandto_arraywith types similar to those of the corresponding functions in module MoreArray. A few modules are included with the necessary functions for lists, arrays, lazy lists strings and streams.
Stream comprehension
If you’re using the original syntax, you may already write
[< >] (*The empty stream*)
[< '1>] (*The stream containing 1*)
[< '1;'2 >] (*The stream containing 1 and 2*)
[< '1; '2; [< '3; '4>] >] (*The stream containing 1,2,3 and 4*)
With this extension, stream ranges may now be written
[< 1 .. 20 >]
[< `0; `1; 2..18; `19; `20 >]
let a = 1 and b = 20 in [< `a .. `b >]
[< (0+1)..19; `20 >]
If you’re using the revised syntax, you may still write
[: :] (*The empty stream*)
[: `1:] (*The stream containing 1*)
[: `1;`2 :] (*The stream containing 1 and 2*)
[: `1; `2; [: `3; `4:] :] (*The stream containing 1,2,3 and 4*)
and now
[: 1 .. 20 :]
[:`0;`1;2..18;`19;`20 :]
let a = 1 and b = 20 in [: `a .. `b :]
[: (0+1)..19;`20 :]
These expressions produce the stream of integers between 1 and 20. Concatenations, when
needed, are performed lazily, at run-time.
- This feature requires module MoreStream, included in this distribution as source file moreList.ml .
- This feature requires module Sdflow, included in this distribution as source file sdflow.ml .
This extension also adds stream comprehension loops may be written, either in the original syntax
[< i+1 | i <- [< '1;'2;'3;'4;'5 >] >] (*The stream [<'2; '3; '4; '5; '6>] *)
[< i+1 | i <- [< '1;'2;'3;'4;'5 >] ; i mod 2 = 0 >] (*The stream [<'3; '5>] *)
[<(i,j)| i <- [< '1;'2 >] ; j <- [< '3;'4 >] >] (*The stream [<'(1,3); '(1,4); '(2,3); '(2,4)>] *)
or,in the revised syntax
[: i+1 | i <- [:`1;`2;`3;`4;`5:] :] (*The stream [:`2;`3;`4;`5;`6:] *)
[: i+1 | i <- [:`1;`2;`3;`4;`5:] ; i mod 2 = 0:] (*The stream [:`3;`5:] *)
[:(i,j)| i <- [:`1;`2:] ; j <- [:`3;`4:] :] (*The stream [:`(1,3);`(1,4);`(2,3);`(2,4):] *)
In addition, stream comprehension loops may be read from other data structures
(”cross-comprehension”)
[< i | (MoreString) i <- "aeiou" >] (*The stream [<'"a";'"e";'"i";'"o";'"u">] *)
[: i | (MoreString) i <- "aeiou" :] (*The stream [:`"a";`"e";`"i";`"o";`"u":] *)
- This feature works with any module containing functions
map,filter,flatten,map_filterandto_streamwith types similar to those of the corresponding functions in module MoreArray. A few modules are included with the necessary functions for lists, arrays, lazy lists strings and streams. - If you use this feature, do take a look at Sdflow for additional operators, such as parallel composition, etc.
Lazy List comprehension
Lazy Lists are defined in module LList
Lazy Lists may be written either using LList.Nil and LList.Cons or using
the following syntax
[^ ^] (*The empty lazy list*)
[^ 1 ^] (*The lazy list containing 1*)
[^ 1;2 ^] (*The lazy list containing 1 and 2*)
Plus, if you’re using the original syntax
1 ^:^ [^ 2;3;4 ^]
or, if you’re using the revised syntax
[^ 1 :: [^ 2;3;4 ^] ^] .
In addition, lazy list ranges may be written, in either syntax
[^ 1 .. 20 ^]
[^ 0;1;2..18;19;20 ^]
let a = 1 and b = 20 in [^ a .. b ^]
[^ (0+1)..19;20 ^]
All these expressions produce the lazy list of integers between 1 and 20. These lazy lists are always
computed at run-time, lazily.
- This feature requires module MoreLazy List, included in this distribution as source file moreList.ml .
As for lists, lazy list comprehension loops may be written
[^ i+1 | i <- [^ 1;2;3;4;5 ^] ^] (*The lazy list [^ 2;3;4;5;6 ^] *)
[^ i+1 | i <- [^ 1;2;3;4;5 ^] ; i mod 2 = 0 ^] (*The lazy list [^ 3;5 ^] *)
[^ (i,j)| i <- [^ 1;2 ^] ; j <- [^ 3;4 ^] ^] (*The lazy list [^ (1,3);(1,4);(2,3);(2,4) ^] *)
In addition, lazy list comprehension loops may now be read from other data structures
(”cross-comprehension”)
[^ i | (MoreString) i <- "aeiou" ^] (*The lazy list [^ 'a';'e';'i';'o';'u' ^] *)
- This feature works with any module containing functions
map,filter,flatten,map_filterandto_lazylistwith types similar to those of the corresponding functions in module MoreArray. A few modules are included with the necessary functions for lists, arrays, lazy lists strings and streams.
Some code is inlined from Camlp4 3.10’s source code by Daniel de Rauglaudre and Nicolas Pouillard.
You may find Camlp4 at http://www.ocaml.org .
Loops
This is an expansion of Likai Liu’s Camlp4 3.10/Foreach Tutorial, available as part of the OCaml Tutorial.
OCaml allows writing
for i = 0 to n do
(*bla*)
done
With the Loop syntax extensions, one may write
for each i in MoreStream [: 1 .. n :] do
print_int i
done (*Maps to MoreStream.iter (fun i -> print_int i) [: 1 .. n :] *)
for each i c in Array.iteri [| 'a'; 'b'; 'c'; 'd' |] do
Printf.printf “%d -> %c\n” i c
done (*Maps to Array.iteri (fun i c -> Printf.printf “%d -> %c\n” i c) [| 'a'; 'b'; 'c'; 'd' |] *)
for each (x,y) in List [| (1,2); (3,4); (5,6) |] do
Printf.printf “(%d,%d)\n” x y
done (*Maps to List.iter (fun (x,y) -> Printf.printf “(%d,%d)\n” x y) [| (1,2); (3,4); (5,6) |] *)
More generally, there are two syntaxes:
for each pattern_1 pattern2 … in Module value do
some_body
done (*Maps to Module.iter (fun pattern_1 pattern_2 … -> some_body) value *)
or
for each pattern_1 pattern2 … in function_identifier value do
some_body
done (*Maps to function_identifier (fun pattern_1 pattern_2 … -> some_body) value *)
Modules
Documentation of the modules may be found here.
Flows
This packages contains a verbatim inclusion of Zheng Li’s SDFlow 0.01, included here as
- it’s not a very common library (it’s not available with GODI, in particular)
- it’s a dependency of MoreStream
MoreArray, MoreStream, MoreString, MoreList, LList
Various utilities for manipulation of arrays, streams, strings, lists and lazy lists. These utilities are necessary for the corresponding comprehensions. Documentation
Comprehension for OCaml « Il y a du thé renversé au bord de la table a dit,
décembre 18, 2007 à 12:26
[...] Publié dans En français, Enseignement, In English, Informatique, Recherche tagged arrays, camlp4, chaînes de caractères, data structures, flux, haskell, laziness, lazy, list comprehension, listes, listes paresseuses, lists, ocaml, programmation, programming, streams, strings, structures de données, sucre syntaxique, syntaxe, tableaux à 12:26 par yoric I have just released a first version of a syntax extension for OCaml, improving comprehension for lists, strings, streams, lazy lists and arrays. More informations here. [...]