More fun with list comprehensions...I started investigating some of the language plugins for Dr. Scheme and found out that one of them (Swindle) support Haskell-like list comprehensions [1].
Here's a very simple list comprehension in Swindle:
>(list-of x (x <- '(1 2 3))
(1 2 3)
list-of is one of several collectors; there are others. For example, using product-of instead of list-of evaluates to 6 in the above example.
Projections on the accumulated data are handled thusly:
> (list-of (list x (* x x)) (x <- '(1 2 3)))
((1 1) (2 4) (3 9))
Similar to Haskell, Swindle supports range definitions in the generator:
> (list-of x (x <- 0 2 .. 10))
(0 2 4 6 8 10)
Using clauses like where and until combined with predicates gets interesting:
> (define (less-than-5 x) (< x 5))
> (list-of x (x <- 0 1 .. while less-than-5))
(0 1 2 3 4)
You can even write the world's wierdest for loop:
> (loop-for (x <- 0 then (+ x 1) until (= x 10)) do (display x))
0123456789
Comprehensions in Swindle support arbitrary numbers of generators. For example, here's a simple Cartesian product:
>(list-of (list x y) (x <- '(a b c)) (y <- '(1 2 3)))
((a 1) (a 2) (a 3) (b 1) (b 2) (b 3) (c 1) (c 2) (c 3))
You can use the when clause to apply filtering:
> (list-of (list x y) (x <- '(1 2 3)) (y <- '(1 2 3)) when (<= y x))
((1 1) (2 1) (2 2) (3 1) (3 2) (3 3))
Swindle also supports the ability to define your own iterators as one-arg functions:
> (define (foo yield)
(yield 'hello)
(yield 'list)
(yield 'comprehensions)
(yield collect-final))
> (list-of x (x <- (function-iterator foo)))
(hello list comprehensions)
Not sure why I explicitly have to yield collect-final in that example, especially given this output:
> (list-of x (x <- (lambda (yield) (yield 'hello) (yield 'world))))
(hello world)
Anyway, pretty cool stuff. Sort of lessens my desire to learn Haskell now, though :)
[1] It looks like Swindle has pretty much everything and the kitchen sink. Sometimes two kitchen sinks, from the looks of things. Need to check this out more.
