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]
# [(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 ()
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
()
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
3 Responses to "List comprehension in OCaml"
[...] 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 [...]
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/
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