Search code examples
lispcommon-lispmultiplication

multiplying each element of a list with each element of another list in lisp


i want to write a function that accepts 2 lists as argument and return multiplication of them in a list. like this:

(3 4) (3 5 6) => (9 15 18 12 20 24)

this is the code that i've came up with but i receive an error which is telling me that i have too few arguments for map.

(defun multip (lst lst2)
    ;this is a function to flatten the result
   (defun flatten (tree)
     (let ((result '()))
       (labels ((scan (item)
           (if (listp item)
               (map nil #'scan item)
               (push item result))))
                  (scan tree))
                       (nreverse result)))
(flatten (map (lambda (i) (map (lambda (j) (* i j)) lst )) lst2))
 )

   (write  (multip '(3 4 6) '(3 2) ))

i can not understand what am i doing wrong. i appreciate your comment.


Solution

  • You should use mapcar instead of map:

    (mapcar (lambda (i) (mapcar (lambda (j) (* i j)) lst )) lst2))
    

    These are two different functions: mapcar maps a function on one or more lists, and requires at least two arguments, while map is the equivalent but for any kind of sequences (e.g. vectors), and requires an additional argument specifying the type of the result. See the reference for map here, and the reference for mapcar here.

    Style

    You are using a defun inside another defun: this is not good style, since every time multip is called it redefines globally the function flatten. You should either define flatten externally, only once, or use a local declaration of function with flet or labels (as for the internal function scan inside flatten.)

    For alternative and more simple definitions of flatten, you can see this question in SO.