#lang racket ; If X = (x_0 x_1 ... x_n) and Y = (y_0 y_1 ... y_m) then ; (fmap2lcm fn X Y) ; is the list (r_0 r_1 ... r_l) where where the element r_i ; in position i is (fn x_(i mod n) y_(i mod m)) ; and l = lcm(m, n) where lcm - least common multiple. ; ; In other words the map is performed by reusing the lists X and Y until ; they both end at the same time. ; Example: (fmap2lcm list '(1 2) '(3 4 5)) is ; ((1 3) (2 4) (1 5) (2 3) (1 4) (2 5)) ; Cleanup: ; This is not so much a cleanup as an optimization to show to use accumulators ; to introduce tail-recursion (define fmap2lcm (lambda (fn X Y) ; recursor (define fmap2lcm-r (lambda (fn X-cur Y-cur result) ( let ( ; wrap X-cur and Y-cur if they are finished [ X-r (if (null? X-cur) X X-cur) ] [ Y-r (if (null? Y-cur) Y Y-cur) ] ) (if (and (null? X-cur) (null? Y-cur)) ; when both empty have hit the lcm, finish by reversing the ; result accumulator (reverse result) ; otherwise process one more element and recurse (fmap2lcm-r fn (rest X-r) (rest Y-r) ; add the element to the accumulator, and then recurse (cons (fn (first X-r) (first Y-r)) result)) ) ) )) ; end of fmap2lcm-r ; handle special boundary case of empty input lists ; result accumulator needs to be reversed (if (or (null? X) (null? Y)) '() (fmap2lcm-r fn X Y '() ) ) ))