Question

This is homework, so I don't want the answer. I only need a push in the right direction. I am required to map multiple functions onto a list. For instance:

(map-multi (list plus-one square) '(4 5 6)) => (25 36 49)

I am able to have it map the first function to the elements of the list, however, I get very lost after that. Also, since this is introductory, I am limited to introductory functions (const, append, car, cdr, member, etc.)

(define (map-multi f l)  
    (cond  
        ((null? l)  
            l)  
        (else (cons ((car f) (car l))  
            (map-multi f (cdr l))))))  
Was it helpful?

Solution

You need to compose the functions you receive in the f parameter. For simplicity's sake, let's say that there are only two functions in the list - then you need to apply the first function to the current element in the list of numbers and then apply the second function to the result of that. If you can use the compose procedure go ahead with it and change this line in your code:

((car f) (car l)) ; you're applying only the 1st function! what about the 2nd?

... with this one:

((compose (cadr f) (car f)) (car l))       ; now we're applying both functions

If you can't use compose, then replace the same line with this one:

((cadr f) ((car f) (car l)))               ; now we're applying both functions

Now, if the problem is more general and you're required to map a list of functions with more than two elements, then once more replace the same line in your code with this:

((compose-multi f) (car l))

And implement a helper function that composes and returns all the functions in the list, by successive calls to compose. This one is left as an exercise for you, given that it's homework - but if you understand how the above code works for just two functions, it should be easy enough to extend the result for a list of multiple functions:

(define (compose-multi flist)      ; procedure for composing a list of functions
  (if (null? flist)                ; if the list is empty then
      <???>                        ; return the identity function
      (<???> (compose-multi <???>) ; else compose the result of recursive call
             <???>)))              ; with the current element in the list

Notice that the identity function is required for handling the case where there are no elements in the list of functions; it's very simple to define, it just returns the same value that was passed as parameter.

Also be aware that compose-multi returns a function, the result of composing all the functions in the list - compose does this for you, but if you're not allowed to use it just remember that this:

(compose x y)

... is equivalent to this:

(lambda (n) (x (y n)))

OTHER TIPS

It might be easier to write this as two functions. One takes a list of functions and a single input, and applies all the functions in the list in series. The output from one function application will be the input for the next one; once you run out of functions you're done.

The other function will simply map this helper function across a list of inputs.

Here is an alternate way to define multi-map which instead of composition uses the operation called fold. Since you're only allowed to use introductory functions, this is not really the answer to your assignment. But it will be, if you write your own definition of fold (it isn't very long!)

(define (multi-map operations input)
  (fold map input operations))

> (multi-map (list 1+ square)
             '(4 10 8))
$2 = (25 121 81)

> (multi-map (list 1+ square 1+) 
             '(4 10 8))
$3 = (26 122 82)

To get warm, start with a simpler problem. Then generalize the solution.

How would you write this function?

(define (map-single fs x)
  ...)

> (map-single (list double add1) 3)
7

That takes a list, fs, of function values as argument and a number, x, and computed the value of applying the (composition of) functions in fs to x?

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