Question

I am having trouble calling map over a list of lists.

01>(define (foldr f accum xs)
  (if (null? xs) accum
      (f (car xs) (foldr f accum (cdr xs)))))

02> (map (lambda xs foldr cons '() xs) '(1 2) '(3 4) '(5 6))

((1 3 5) (2 4 6))

this is what we want, but I can't get this to work from a callable function.

EDIT -- (map (lambda x x) '(1 2) '(3 4) '(5 6)) gives the same result!

03> (define (zip . xs)
    (map (lambda ys foldr cons '() ys) xs)))

04> (zip '(1 2) '(3 4) '(5 6))

(((1 2)) ((3 4)) ((5 6)))

I can see the problem that the arguments passed to zip become a list, but I do not know hot to keep treating them as I did with the working version.

I am not sure how apply is used with map

05> (define zip
  (lambda xs
    (apply (map (lambda ys foldr cons '() ys)) xs)))

06> (zip '(1 2) '(3 4) '(5 6))

*** ERROR IN zip, (stdin)@546.12 -- Wrong number of arguments passed to procedure (map '#<procedure #49>)

this makes sense as map is not calling anything. ;; but then how could we apply map to the same args that map calls for the fold function?

07> (define (zip . args)
  (apply (lambda xs (map (lambda ys foldr cons '() ys) xs)) args))

08> (zip '(1 2) '(3 4) '(5 6))

(((1 2)) ((3 4)) ((5 6)))

which is just the same a the first attempt. I'm sure (...hope) that I am missing something tiny here.

Was it helpful?

Solution

The zip function is in my Standard Prelude.

> (define (zip . xss) (apply map list xss))
> (zip '(1 2 3) '(a b c))
((1 a) (2 b) (3 c))
> (zip '(1 2 3) '(a b c) '(x y z))
((1 a x) (2 b y) (3 c z))

OTHER TIPS

(define (zip . xs)  
 (if (null? (car xs))
      '()
      (cons (map car xs)
            (apply zip (map cdr xs)))))

(zip '(1 2) '(3 4) '(5 6))

;Value 13: ((1 3 5) (2 4 6))

As you can see it doesn't really fit the map pattern. The behavior you observe earlier is a bit non-standard where map given a function and multiple lists will return a list created by applying the function to matching terms in the lists.

They way to re-introduce the behavior would be to use apply, but you can't apply map directly, and wrapping it up properly in a anonymous function is hard to do.

You were on a good track with

(define (zip . args) (apply (lambda xs (map (lambda ys foldr cons '() ys) xs)) args))

But that doesn't leverage the special behavior seen before. Where that xs of the xs)) args) is, is where you want to see first-xs second-xs ... last-xs) and to actually do it that way in all likelyhood requires a macro

You're better off just implementing the logic on the multi-map method directly.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top