List comprehension in OCaml

A nifty thing when working with list is to use list comprehension. This is something natural for a python programmer :

l1 = [(1,2),(2,3),(3,4),(4,5),(5,6),(6,7)]
# [(1, 2), (2, 3), (3, 4), (4, 5), (5, 6), (6, 7)]
l2 = [2*x+y for (x,y) in l1]
# [4, 7, 10, 13, 16, 19]
l3 = [x for x in l2 if x > 12]
# [13, 16, 19]

It is however absent from OCaml… Of course, it can be emulated:

let l1 = [1,2;2,3;3,4;4,5;5,6;6,7]  in
let l2 = (fun fmap l -> List.rev_map fmap (List.rev l)) (fun (x,y) -> 2*x+y) l1 in
let l3 = (fun ffilt fmap l ->
    let rev_filter f l =
      let rec aux d = fun
      [  [] -> d
      | [t::q] -> aux (if f t then [t::d] else d) q]
      in
      aux [] l
    in
    List.rev_map fmap (rev_filter ffilt l)) (fun x -> x > 12) (fun x -> x) l2
in ()

But this is really too much… Wouldn't it be nice to write something like that :

let l1 = [1,2;2,3;3,4;4,5;5,6;6,7]  in
let l2 = [+ 2*x+y | (x,y) <- l1] in
let l3 = [+ x | x <- l2 when x > 12] in
()

The [+ (* ... *)] indicates that this is a list comprehension. This actually is possible using camlp4 ;)

Downloaded : 108 times
File : listcomp.tar.gz
Size: 841 o

3 Responses to "List comprehension in OCaml"

Friggeri.net : Archive : Ce qu'il faudrait ajouter à la syntaxe OCaml says:

[...] m'être amusé rapidement ce matin avec camlp4, je me dis que pour écrire mon window manager, ça pourrait être très sympa de le [...]

Yoric says:

Deux remarques :
* Camlp4 contient par défault la compréhension des listes, même si ce n'est pas documenté.
* J'ai mis en ligne il y a quelques semaines une version plus complète, avec compréhension des listes, tableaux, flux et listes paresseuses et conversions de l'un à l'autre [1]. La version qui est sur mon disque dur permet aussi le filtrage par motifs sur les listes paresseuses, d'ailleurs.

http://dutherenverseauborddelatable.wordpress.com/2007/12/18/comprehension-for-ocaml/

Michaël Le Barbier says:

But this is really too much… Wouldn't it be nice to write something like that :

let l1 = [1,2;2,3;3,4;4,5;5,6;6,7] in
let l2 = List.map (fun (x,y) -> 2*x+y) l1 in
let l3 = List.filter ((>=) 12) l2 in
()

Can you explain why you do not choose this way to deal with your "comprehension example", I am curious? (I do not know comprehension but I guess it is a sort of intrusion of higher order functions in Python, am I wrong?)

Leave a Reply