Saturday, August 12, 2006

Eager Comprehensions for Black Belts - 3. Multiple generators (nested loops) and qualifiers (filtering)

3. Multiple Generators (nested loops) and qualifiers (filtering)

Comprehensions allow multiple generators. Consider:

(list-ec (: x 2)
(: y 3)
(list x y)) ; => ((0 0) (0 1) (0 2)
; (1 0) (1 1) (1 2))
The inner (last) generator spins faster than the outer generator. Since the scope of variables bound by a generator begins after the generator expression, it is possible to refer to variables bound by previous generators.

(list-ec (: x 3)
(: y (+ x 1))
(list x y)) ; => ((0 0)
; (1 0) (1 1)
; (2 0) (2 1) (2 2))
At this point we are capable of generating loads of values, but sometimes we want to skip some of them.

Consider the problem of finding small integers such that:
  x^2 + y^2 = z^2 .
A valid strategy is to let x, y and z run from, say, 1 to 100, and skip the triples which doesn't fulfill the equation. To mimic this strategy we will use qualifiers.

The following qualifiers are available for filtering:
  
(if <test>)
(not <test>*)
(and <test>*
(or <test>*)
[Besides the filtering qualifiers all generators, as well as
(begin <sequence>) and (nested <qualifier>*) are also qualifiers.]

(list-ec (: x 1 100)
(: y x 100)
(: z y 100)
(if (= (+ (* x x) (* y y))
(* z z)))
(list x y z)) ; => ((3 4 5)
; (5 12 13)
; (6 8 10)
; ...
; (60 63 87)
; (65 72 97))
The common cases (if (not <test>)), (if (and <test>*)), and (if (or <test>*)) are abbreviated by (not <test>), (and <test>*), and (or <test>*).
    
(list-ec (: x 1 4)
(: y 1 4)
(not (= x y))
(list x y)) ; => ((1 2) (1 3)
; (2 1) (2 3)
; (3 1) (3 2))

Labels:

0 Comments:

Post a Comment

<< Home