# Just Launched: You can now import projects and releases from Google Code onto SourceForge

We are excited to release new functionality to enable a 1-click import from Google Code onto the Allura platform on SourceForge. You can import tickets, wikis, source, releases, and more with a few simple steps.

## Re: [Series-users] Nested loops

 Re: [Series-users] Nested loops From: Helmut Eller - 2010-07-23 16:26:11 ```* Raymond Toy [2010-07-23 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 ```

### Thread view

 [Series-users] Nested loops From: Helmut Eller - 2010-07-23 08:53:29 ```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) Or as picture: ----------------- ------- | (scan '(a b c)) |------>| |----> #z(a b c a b c a b c) ----------------- | | | cross | ----------------- | | | (scan '(1 2 3)) |------>| |----> #z(1 1 1 2 2 2 3 3 3) ----------------- ------- I tried this: (defmacro cross (sx sy) `(producing (ox oy) ((genx ,sx) x geny y) (loop (tagbody (setq x (next-in genx (terminate-producing))) (setq geny (generator ,sy)) loop (setq y (progn (next-in geny (go end)))) (next-out ox x) (next-out oy y) (go loop) end)))) (defun foo () (collect (mapping (((x y) (cross (scan '(1 2 3)) (scan '(a b c))))) (cons x y)))) It works but apparently this can't be optimized. Is there a better way to write such "nested loops" where the outputs are "faster" than the inputs? If not, would it be possible to add a new "primitive" for such cases? Helmut ```
 Re: [Series-users] Nested loops From: Helmut Eller - 2010-07-23 16:26:11 ```* Raymond Toy [2010-07-23 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 ```
 Re: [Series-users] Nested loops From: Raymond Toy - 2010-07-26 00:13:58 ``` On 7/23/10 12:25 PM, Helmut Eller wrote: > * Raymond Toy [2010-07-23 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). Sorry, I'm still confused. If the series have infinite length, then the first series from cross will repeat the first element forever? Or something else? > >> 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. This produces something different from the original cross. I get (cross (scan '(a b c)) (scan '(1 2 3))) -> #Z(a a a b b b c c c) #z(1 2 3 1 2 3 1 2 3) > 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 What is the value of m? How is it derived from the inputs? I think it's ok if the output of a series function is "faster" than the inputs. The function SPREAD produces more output data than the input data series. Ray ```
 Re: [Series-users] Nested loops From: Helmut Eller - 2010-07-26 06:19:22 ```* Raymond Toy [2010-07-26 02:13+0200] writes: > On 7/23/10 12:25 PM, Helmut Eller wrote: >> * Raymond Toy [2010-07-23 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). > Sorry, I'm still confused. If the series have infinite length, then the > first series from cross will repeat the first element forever? Or > something else? Yes, it's repeated. [But in a lazy fashion, so that the version with ITERATE wouldn't work if the client only consumes the first 10 elements.] >> >>> 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. > This produces something different from the original cross. I get > > (cross (scan '(a b c)) (scan '(1 2 3))) -> > #Z(a a a b b b c c c) > #z(1 2 3 1 2 3 1 2 3) That's the same as what I quoted above, no? >> 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 > What is the value of m? In the example it's 3; #z(y_i_0 y_i_1 ... y_i_m) corresponds to one of the #z(1 2 3) segments. > How is it derived from the inputs? I realize now that the second argument of cross can't be a just a series it must be a function that produces a series (the current element of the first series is passed in as argument). It's that function that decides how long the segments get. > I think it's ok if the output of a series function is "faster" than the > inputs. The function SPREAD produces more output data than the input > data series. Yes, that looks promising. I'm trying to write some examples here http://projectfortress.sun.com/Projects/Community/wiki/ComprehendingComprehensions with series. They enumerate Pythagorean Triples with generator expressions. It feels like that should be possible with series too, but actually doing it is quite hard. Helmut ```
 Re: [Series-users] Nested loops From: Raymond Toy - 2010-07-26 13:07:13 ``` On 7/26/10 2:19 AM, Helmut Eller wrote: > >> This produces something different from the original cross. I get >> >> (cross (scan '(a b c)) (scan '(1 2 3))) -> >> #Z(a a a b b b c c c) >> #z(1 2 3 1 2 3 1 2 3) > That's the same as what I quoted above, no? Yes. I don't know what I was looking at. For some reason, I thought the original was #z(1 1 1 2 2 2 3 3 3). > > I'm trying to write some examples here > http://projectfortress.sun.com/Projects/Community/wiki/ComprehendingComprehensions > > with series. They enumerate Pythagorean Triples with generator > expressions. It feels like that should be possible with series too, > but actually doing it is quite hard. Ah, now I understand. We have 3 sets of numbers, a, b, c, and we want to take all possible combinations of those 3 numbers so that we can apply the coprime property, the ordering a < b < c, and the most important property of a^2+b^2 = c^2. So to do this with series, we need to generate series as you propose so that we eventually get all possible combinations of a, b, and c. Ray ```