From: Helmut Eller <heller@co...>  20100723 16:26:11

* Raymond Toy [20100723 15:00+0200] writes: > On 7/23/10 4:15 AM, Helmut Eller wrote: >> Hello, >> >> I'd like to create a macro/function that when given two series >> as input produces the "cross product" as output. E.g. >> >> (cross (scan '(a b c)) (scan '(1 2 3))) >> => #Z(a a a b b b c c c) and #Z(1 2 3 1 2 3 1 2 3) >> > Do the two series have the same length? Yes, the output series have the same length (possibly infinite). > It seems you just replicate > each element 3 times. Why 3? Because there are 3 elements in the > original series? Perhaps a bad example, but yes: 3 because the inputs have length 3. > I'm a bit confused on exactly what cross should do. Another way to write CROSS would be: (defmacro cross (sx sy) `(let ((xs '()) (ys '())) (iterate ((x ,sx)) (iterate ((y ,sy)) (push x xs) (push y ys))) (values (scan (reverse xs)) (scan (reverse ys))))) Obviously inefficient, but hopefully clearer. One series expression drives the outer loop and the other series expression drives the inner loop. The outer loop produces a series; lets call that #z(x_0 x_1 ... x_n). The inner loop consumes that series. For each element x_i the inner loop produces (part of) a series #z(y_i_0 y_i_1 ... y_i_m) and additionally copies x_i m times to a second series (so that clients of CROSS can access the corresponding x and y values). The final two outputs look like: #z(x_0 x_0 ... x_0 x_1 x_1 ... x_1 x_2 x_2 ...) #z(y_0_0 y_0_1 ... y_0_m y_1_0 y_1_1 ... y_1_k y_2_0 y_2_1 ...) y_0_0 and y_1_0 can be different; also m and k can be different. The inner loop doesn't necessarily produce the same values for each iteration of the outer loop; i.e. the y values aren't just replicated. [The series expression of the inner loop should also have access to the current x value. In the example that's possible by accessing the variable x but that's sloppy; the name should better be an argument to CROSS or the second expression should be a lambda taking the value of x as argument.] Helmut 