From: lispuser
Subject: mapcar use.
Date: 
Message-ID: <1140924801.222606.320260@z34g2000cwc.googlegroups.com>
Hello all,
I am trying to use the mapcar function for the multiplication of 2
lists as :
(1 2) and (4 5 6)
so that the result which i get is
as
((4 5 6) (8 10 12))
I am still not gettin how to use eval and mapcar to achieve this...
Can somebody help me...
thanks

From: verec
Subject: Re: mapcar use.
Date: 
Message-ID: <44012821$0$1168$5a6aecb4@news.aaisp.net.uk>
On 2006-02-26 03:33:21 +0000, "lispuser" <·········@yahoo.co.in> said:

> Hello all,
> I am trying to use the mapcar function for the multiplication of 2
> lists as :
> (1 2) and (4 5 6)
> so that the result which i get is
> as
> ((4 5 6) (8 10 12))
> I am still not gettin how to use eval and mapcar to achieve this...
> Can somebody help me...
> thanks

(defun mul-list (list-1 list-2)
  "Multiplies all elements of list-2 by the successive elements of list-1"
  (let ((res nil))
    (dolist (x list-1)
      (setf res
            (append res
                    (list
                     (mapcar (lambda (a)
                               (when a
                                 (* a x)))
                             list-2)))))
    res))

CL-USER 2 > (mul-list '(1 2) '(4 5 6))
((4 5 6) (8 10 12))

CL-USER 3 > (mul-list '(1 2 3) '(4 5 6))
((4 5 6) (8 10 12) (12 15 18))


But I'm sure more advanced lispers will come up with
lovely one-liners :-)
--
JFB
From: Carl Shapiro
Subject: Re: mapcar use.
Date: 
Message-ID: <ouy3bi6u4mn.fsf@panix3.panix.com>
verec <·····@mac.com> writes:

> But I'm sure more advanced lispers will come up with
> lovely one-liners :-)

(defun f (x y)
  (mapcar (lambda (i) (mapcar (lambda (j) (* i j)) y)) x))
From: Coby Beck
Subject: Re: mapcar use.
Date: 
Message-ID: <e0aMf.4967$Cp4.2147@edtnps90>
"verec" <·····@mac.com> wrote in message 
·····························@news.aaisp.net.uk...
> On 2006-02-26 03:33:21 +0000, "lispuser" <·········@yahoo.co.in> said:
>
> (defun mul-list (list-1 list-2)
>  "Multiplies all elements of list-2 by the successive elements of list-1"
>  (let ((res nil))
>    (dolist (x list-1)
>      (setf res
>            (append res
>                    (list
>                     (mapcar (lambda (a)
>                               (when a
>                                 (* a x)))
>                             list-2)))))
>    res))

(defun doit (a b)
  (loop for x in a collect (loop for y in b collect (* x y))))

> But I'm sure more advanced lispers will come up with
> lovely one-liners :-)

Well, no mapcars but it is one line!

-- 
Coby Beck
(remove #\Space "coby 101 @ bigpond . com")
From: Pascal Bourguignon
Subject: Re: mapcar use.
Date: 
Message-ID: <87lkvyahpf.fsf@thalassa.informatimago.com>
"lispuser" <·········@yahoo.co.in> writes:

> Hello all,
> I am trying to use the mapcar function for the multiplication of 2
> lists as :
> (1 2) and (4 5 6)
> so that the result which i get is
> as
> ((4 5 6) (8 10 12))
> I am still not gettin how to use eval and mapcar to achieve this...
> Can somebody help me...
> thanks

From age 6 to age 18, I was taught in math that you can multiply
cardinals, integers, rationals, decimals, reals, complex, and
matrices.  I heard that there are some other kind of numbers, named
quaternions and octonions.  And I've been taught about scalar product
and external product which allow some kind of "multiplication" of
vectors.  I addition, I've been advised to avoid multiplicating (and
comparing either) apples with oranges.

But I've no idea what the multiplication of two lists can be!

I suspect that you don't have a clear idea of what you mean either.
When you know what you're speaking of, the algorithm and lisp function
is usually a mere and direct transcription.

If you can explain us what you mean by multiplying two lists, perhaps
we could help.

list-� :  L � L  ----> ???
         (l1,l2) |---> ???

-- 
__Pascal Bourguignon__                     http://www.informatimago.com/

HANDLE WITH EXTREME CARE: This product contains minute electrically
charged particles moving at velocities in excess of five hundred
million miles per hour.
From: lispuser
Subject: Re: mapcar use.
Date: 
Message-ID: <1140927649.636097.182730@z34g2000cwc.googlegroups.com>
taking one list as column and the other list as rows and then
multiplyin them ...
From: Kaz Kylheku
Subject: Re: mapcar use.
Date: 
Message-ID: <1140927817.145585.192870@z34g2000cwc.googlegroups.com>
Pascal Bourguignon wrote:
> "lispuser" <·········@yahoo.co.in> writes:
>
> > Hello all,
> > I am trying to use the mapcar function for the multiplication of 2
> > lists as :
> > (1 2) and (4 5 6)
> > so that the result which i get is
> > as
> > ((4 5 6) (8 10 12))
> > I am still not gettin how to use eval and mapcar to achieve this...
> > Can somebody help me...
> > thanks

[ .. snip ... ]

> But I've no idea what the multiplication of two lists can be!

If we take the (1 2) to be a column vector, and the (4 5 6) to be a row
vector, and the ((4 5 6) (8 10 12)) to be two-row, three-column matrix,
then we essentially have what you see here:

http://en.wikipedia.org/wiki/Tensor_product

> I suspect that you don't have a clear idea of what you mean either.
> When you know what you're speaking of, the algorithm and lisp function
> is usually a mere and direct transcription.

Nested MAPCAR-ology can confuse newbies.

(defun product-of-two-rank-1-tensors (left right)
  (mapcar (lambda (left-el)
            (mapcar (lambda (right-el)
                      (* left-el right-el))
                    right))
          left))
From: Alan Crowe
Subject: Re: mapcar use.
Date: 
Message-ID: <86u0aj74cw.fsf@cawtech.freeserve.co.uk>
"Kaz Kylheku" <········@gmail.com> writes:
> Nested MAPCAR-ology can confuse newbies.
> 
> (defun product-of-two-rank-1-tensors (left right)
>   (mapcar (lambda (left-el)
>             (mapcar (lambda (right-el)
>                       (* left-el right-el))
>                     right))
>           left))

It is not hard to see why nested mapcar-ology confuses
newbies. We say that anonymous functions are for when the
function is too simple to deserve a name, but we don't keep
our word. Only one of those two lambda's is too simple to
deserve a name, the one that goes

(lambda (left-el right-el)
  (* left-el right-el))

*pause for theatrical effect* 

Oh shit, that's not correct,
it is

(lambda (right-el) (* left-el right-el))

LEFT-EL is free.

I prefer to write this kind of thing like this

         (defcurry multiply-by (x)(y)(* x y))

         (defcurry apply-scale-factor-to (list)(scale-factor)
           (mapcar (multiply-by scale-factor) list))

         (defun mult (as bs)
           (mapcar (apply-scale-factor-to bs) as))

CL-USER> (mult '(1 2) '(4 5 6))
=> ((4 5 6) (8 10 12))

where defcurry is my lambda-hiding macro:

         (defmacro defcurry (name arg1 arg2 &body code)
           `(defun ,name ,arg1
             (lambda ,arg2 ,@code)))

Alan Crowe
Edinburgh
Scotland
From: Kaz Kylheku
Subject: Re: mapcar use.
Date: 
Message-ID: <1141152820.599494.213030@i39g2000cwa.googlegroups.com>
Alan Crowe wrote:
> "Kaz Kylheku" <········@gmail.com> writes:
> > Nested MAPCAR-ology can confuse newbies.
> >
> > (defun product-of-two-rank-1-tensors (left right)
> >   (mapcar (lambda (left-el)
> >             (mapcar (lambda (right-el)
> >                       (* left-el right-el))
> >                     right))
> >           left))
>
> It is not hard to see why nested mapcar-ology confuses
> newbies. We say that anonymous functions are for when the
> function is too simple to deserve a name, but we don't keep
> our word.

Another problem is quite simply the MAPCAR syntax itself: namely that
the list arguments are last! A flavor of mapcar that processes only one
list could put that list before the lambda:

  (mapcar* left-list
    (lambda (left-el)
      (mapcar* right-list
        (lambda (right-el) (* left-el right-el)))))

You see how much more readable that is? Everything is in order:

LEFT-LIST, LEFT-EL, RIGHT-LIST, RIGHT-EL,  *.

Or:

"For each LEFT-LIST element LEFT-L, and each RIGHT-LIST element
RIGHT-EL, multiply them together. The End."

With the MAPCAR syntax, it's all backwards. The lists dangle by
themselves, spaced away from the function into which they serve as
input.

It's as confusing as the

 ((lambda (params ...) huge body) args)

syntax which nobody has written much since LET was invented!! LET
relocates the input sources close to the input port.

Even if MAPCAR allows multiple lists, it can still have that syntax,
because it just has to process its &REST parameters and know that the
last one is the function.

  (defun zip (left-list right-list)
    (mapcar* left-list right-list #'list))

  ;; take two, with useless lambda, showing readability

  (defun zip (left-list right-list)
    (mapcar* left-list right-list #'(lambda (left right) (list left
right)))

Suppose that the lambda becomes really large, spanning multiple lines.
Yet, the two lists will stay close to the beginning, so you can see how
they go into the lambda.

The lambda must come last because of its potentially long body. The
&body is always last, so the thing with the &body should go last.

Hot dang shit! An idea whose time has come, no?

I propose a library of inline functions which does this. Take all the
MAP* names and turn them into PAM*.  PAMC, PAML, PAMCAR, PAMCON. :)
From: ····@unreal.uncom
Subject: Re: mapcar use.
Date: 
Message-ID: <5lj902dqpbl6264q59roc9f8ldr0irk72r@4ax.com>
On 28 Feb 2006 10:53:40 -0800, "Kaz Kylheku" <········@gmail.com>
wrote:

>Another problem is quite simply the MAPCAR syntax itself: namely that
>the list arguments are last! A flavor of mapcar that processes only one
>list could put that list before the lambda:
>
>  (mapcar* left-list

Since the purpose of your mapcar* is to let the lamda span multiple
lines more neatly, it's useful only when you use a lambda, not just a
function name.  Therefore it can assume the lambda.  The lambda can be
implicit.  Then what we have is not really a mapcar, but more like a
collecting version of dolist.
From: Pascal Bourguignon
Subject: Re: mapcar use.
Date: 
Message-ID: <87wtff46p5.fsf@thalassa.informatimago.com>
"Kaz Kylheku" <········@gmail.com> writes:
> Even if MAPCAR allows multiple lists, it can still have that syntax,
> because it just has to process its &REST parameters and know that the
> last one is the function.

syntax -->  macro

It's better to write a macro to change the order of mapcar than to put
the function as last argument, because this would imply more consing
at run-time.


> [...]
> Suppose that the lambda becomes really large, spanning multiple lines.
> Yet, the two lists will stay close to the beginning, so you can see how
> they go into the lambda.


Do you need help writing macros?


-- 
__Pascal Bourguignon__                     http://www.informatimago.com/

"Our users will know fear and cower before our software! Ship it!
Ship it and let them flee like the dogs they are!"
From: Kaz Kylheku
Subject: Re: mapcar use.
Date: 
Message-ID: <1141158465.915676.295010@z34g2000cwc.googlegroups.com>
Pascal Bourguignon wrote:
> "Kaz Kylheku" <········@gmail.com> writes:
> > Even if MAPCAR allows multiple lists, it can still have that syntax,
> > because it just has to process its &REST parameters and know that the
> > last one is the function.

> syntax -->  macro

> It's better to write a macro to change the order of mapcar than to put
> the function as last argument, because this would imply more consing
> at run-time.

I disagree, for several reasons.

Firstly, all of the parameters are evaluated normally. So this would be

one of those "useless" macros whose job can be done by an inline
function.

Secondly, this macro would screw up the order of evaluation which is
expected to be left-to-right. Sure, it may seem inncocuous enough: the
function expression on the far right actually gets evaluated first, and

then the list expressions left to right. Usually those function
expressions are just #'IDENTIFIER or #'(LAMBDA ...) so there are no
side effects. Still, you never know.  So to get the order right, it
would have to use gensyms, so that the code would end up spitting out a

LET block with gensyms, wrapped around the real MAPCAR.

Thirdly, the resulting construct wouldn't be a function, but a macro,
which is a disadvantage. Sometimes MAPCAR is indirected upon:

  (apply #'mapcar #'list matrix)  ;; transpose

I would like users of PAMCAR to be able to do the same kind of thing.

I do agree with the point about consing, since the wrapper has to hack
apart a &rest list and rearrange it. This isn't a problem if you don't
call the real function, but actually implement the thing. It's an
optimization issue.  A compiler macro could be used to recognize
certain common cases, spitting out that code which evaluates things in
the right order. For instance, the syntax

  (pamcar a b)

would be translated by the compiler macro to:

  (let ((#:G001 a) (#:G002 b))
    (mapcar #:G002 #:G001))

allowing PAMCAR to remain a function.
From: Pascal Bourguignon
Subject: Re: mapcar use.
Date: 
Message-ID: <87fym33z3z.fsf@thalassa.informatimago.com>
"Kaz Kylheku" <········@gmail.com> writes:

> Pascal Bourguignon wrote:
>> "Kaz Kylheku" <········@gmail.com> writes:
>> > Even if MAPCAR allows multiple lists, it can still have that syntax,
>> > because it just has to process its &REST parameters and know that the
>> > last one is the function.
>>
>> syntax -->  macro
>>
>> It's better to write a macro to change the order of mapcar than to put
>> the function as last argument, because this would imply more consing
>> at run-time.
>
> I disagree, for several reasons.
>
> Firstly, all of the parameters are evaluated normally. So this would be
> one of those "useless" macros whose job can be done by an inline
> function.

With a macro, instead of writing:

(pamcar l1 l2 l3 (lambda (a1 a2 a2)
                     (exp1)
                     (exp2)
                     (exp3)))

you'd just write:

(loop for a1 in l1 
      for a2 in l2
      for a3 in l3 
      do (exp1)
         (exp2)
         (exp3))

Oh oh!  The macro already exists...  Duh!


> Secondly, this macro would screw up the order of evaluation which is
> expected to be left-to-right. [...]

Read again the above loop.

> Thirdly, the resulting construct wouldn't be a function, but a macro,
> which is a disadvantage. Sometimes MAPCAR is indirected upon:
>
>   (apply #'mapcar #'list matrix)  ;; transpose
>
> I would like users of PAMCAR to be able to do the same kind of thing.

You would have to write: 

    (apply (function pamcar) (append matrix (list (funtion list))))


> I do agree with the point about consing, since the wrapper has to hack
> apart a &rest list and rearrange it. This isn't a problem if you don't
> call the real function, but actually implement the thing. It's an
> optimization issue.

The implementaton would be more complex, because either you'd have to
duplicate again the newly consed argument (see above), or you'd have
to have a more complex test for the end of list, to jump over the
function.  


This is a fundamental design issue in LISP:  stuff is built from
simple (KISS principle) lists built from CONS cells, with CONS, FIRST
and REST as primitive.  Anything else (like APPEND, BUTLAST and LAST)
is horribly more complex in time and space, be it directly or indirectly.
 
-- 
__Pascal Bourguignon__                     http://www.informatimago.com/

"You cannot really appreciate Dilbert unless you read it in the
original Klingon"
From: Tobias C. Rittweiler
Subject: Re: mapcar use.
Date: 
Message-ID: <871wxnfam6.fsf@GNUlot.localnet>
"Kaz Kylheku" <········@gmail.com> wrote:

> Another problem is quite simply the MAPCAR syntax itself: namely that
> the list arguments are last! A flavor of mapcar that processes only one
> list could put that list before the lambda:
>
>   (mapcar* left-list
>     (lambda (left-el)
>       (mapcar* right-list
>         (lambda (right-el) (* left-el right-el)))))

I've thought about that as a misfortune, too, because especially with
non-trivial lambda functions, the standard way feels "unnatural", as you
have to skip the lambda code block at first to take a look at what
you're actually mapping through---which is contextual information that
you mostly need to grok what the code block is supposed to do.

And, in my experience, letting your eye focus jump over the lambda right
away to the right place may not be that easy at all, ie. I feel
sometimes forced to mentally line up with an thought vertical bar to see
whether the code line, I just moved my focus to, really belongs to the
MAPCAR I recognized earlier.


On the other hand (and to bring the issue at hand to a perspective), it
recently occured to me that when I'm reading Lisp code, I read very
/structurally/. Ie. I subconsciously recognize certain patterns of code
alignment when I'm in "high level reading" or "loose focus" mode. And a
code bock with the following shape:

  ........
    ..........
      ..................
      .................
      ......................
    ...............

I certainly recognize as "mapping code block". The following would be a
"binding code block":

   ..... ....................
            .....................
            ...................
         .................................
         .............................
    ............................
    ...........................
    ...............................
    ....................


And this one:

   ......
     ..............................
     ..............................
     ..............................
     ..............................

is certainly a LOOP code block. (Additionally there comes the fact that
LOOP is a kind of parenthese free zone; in fact it's funny that the
biggest advantage of ITERATE over LOOP, namely that it does use a
parenthesized syntax, is also somewhat of a disadvantage because I can
very quickly recognize a LOOP block and dechiffer what belongs to LOOP
and what not, in very contrast to ITERATE.)


Whereas the shape of a mapping code block after your accomodation, would
look like a more or less normal "function chaining code block":

  ...................
    ..................
      ......................
      ....................
      .........................


That may very well be a price to pay, though. I'm still undecided over
this, however, but considered this perspective worth sharing anyway.

  -T
From: Barry Margolin
Subject: Re: mapcar use.
Date: 
Message-ID: <barmar-63138C.23244525022006@comcast.dca.giganews.com>
In article <··············@thalassa.informatimago.com>,
 Pascal Bourguignon <······@informatimago.com> wrote:

> But I've no idea what the multiplication of two lists can be!

It was pretty obvious what he means from the example.  Given two lists 
arg1 and arg2, result is a list of lists where

(nth j (nth i result)) == (* (nth i arg1) (nth j arg2))

Given this description, it should be pretty obvious how the OP should go 
about constructing it.

-- 
Barry Margolin, ······@alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***
*** PLEASE don't copy me on replies, I'll read them in the group ***
From: verec
Subject: Re: mapcar use.
Date: 
Message-ID: <44012c09$0$1168$5a6aecb4@news.aaisp.net.uk>
On 2006-02-26 04:04:44 +0000, Pascal Bourguignon 
<······@informatimago.com> said:

> "lispuser" <·········@yahoo.co.in> writes:
> 
>> Hello all,
>> I am trying to use the mapcar function for the multiplication of 2
>> lists as :
>> (1 2) and (4 5 6)
>> so that the result which i get is
>> as
>> ((4 5 6) (8 10 12))
>> I am still not gettin how to use eval and mapcar to achieve this...
>> Can somebody help me...
>> thanks
> 
> From age 6 to age 18, I was taught in math that you can multiply
> cardinals, integers, rationals, decimals, reals, complex, and
> matrices.  I heard that there are some other kind of numbers, named
> quaternions and octonions.  And I've been taught about scalar product
> and external product which allow some kind of "multiplication" of
> vectors.  I addition, I've been advised to avoid multiplicating (and
> comparing either) apples with oranges.
> 
> But I've no idea what the multiplication of two lists can be!

They can be whatever you care to define!

dot-product, cross-product, ... or, in this case
"lispuser-product"

lispuser gave us an example input: '(1 2) '(4 5 6)
and an example output: ((4 5 6) (8 10 12))

> I suspect that you don't have a clear idea of what you mean either.

I'm not sure if this is any of your business. Everyone learns
at his own pace. It may be that the reason why he wants this
is non-sensical, yet it may not be.

At this point, lispuser seems to be stuck on the use of mapcar.
Offer him a solution which removes the mapcar block. Then he
may see that what he asked for is not what he wanted. But not
before the "mapcar road block" is out of the way.
--
JFB
From: Pascal Bourguignon
Subject: Re: mapcar use.
Date: 
Message-ID: <878xrya8n3.fsf@thalassa.informatimago.com>
verec <·····@mac.com> writes:

> On 2006-02-26 04:04:44 +0000, Pascal Bourguignon
> <······@informatimago.com> said:
>
>> "lispuser" <·········@yahoo.co.in> writes:
>> 
>>> Hello all,
>>> I am trying to use the mapcar function for the multiplication of 2
>>> lists as :
>>> (1 2) and (4 5 6)
>>> so that the result which i get is
>>> as
>>> ((4 5 6) (8 10 12))
>>> I am still not gettin how to use eval and mapcar to achieve this...
>>> Can somebody help me...
>>> thanks
>> From age 6 to age 18, I was taught in math that you can multiply
>> cardinals, integers, rationals, decimals, reals, complex, and
>> matrices.  I heard that there are some other kind of numbers, named
>> quaternions and octonions.  And I've been taught about scalar product
>> and external product which allow some kind of "multiplication" of
>> vectors.  I addition, I've been advised to avoid multiplicating (and
>> comparing either) apples with oranges.
>> But I've no idea what the multiplication of two lists can be!
>
> They can be whatever you care to define!
>
> dot-product, cross-product, ... or, in this case
> "lispuser-product"
>
> lispuser gave us an example input: '(1 2) '(4 5 6)
> and an example output: ((4 5 6) (8 10 12))
>
>> I suspect that you don't have a clear idea of what you mean either.
>
> I'm not sure if this is any of your business. Everyone learns
> at his own pace. It may be that the reason why he wants this
> is non-sensical, yet it may not be.

Yes, I'm sorry, I misread, I though the example was what lispuser got
and didn't want.   I'll attribute that to my current ankle pain.  Sorry.


> At this point, lispuser seems to be stuck on the use of mapcar.
> Offer him a solution which removes the mapcar block. Then he
> may see that what he asked for is not what he wanted. But not
> before the "mapcar road block" is out of the way.

Anyways, expliciting the wanted result leads directly to the procedure:

- we want a list of sublists, one for each element in the first argument list,
  each being the product of that element by element of the second argument list:

(mapcar (lambda (element-of-first) 
           (mapcar (lambda (x) (* element-of-first x)) second-list))
        first-list)


-- 
__Pascal Bourguignon__                     http://www.informatimago.com/
I need a new toy.
Tail of black dog keeps good time.
Pounce! Good dog! Good dog!
From: Harald Hanche-Olsen
Subject: Re: mapcar use.
Date: 
Message-ID: <pcohd6m31lc.fsf@shuttle.math.ntnu.no>
+ verec <·····@mac.com>:

| lispuser gave us an example input: '(1 2) '(4 5 6)
| and an example output: ((4 5 6) (8 10 12))

A physicist might call it an outer product; a mathematician might call
it a tensor product.  Or perhaps a Kronecker product?

-- 
* Harald Hanche-Olsen     <URL:http://www.math.ntnu.no/~hanche/>
- It is undesirable to believe a proposition
  when there is no ground whatsoever for supposing it is true.
  -- Bertrand Russell
From: Thomas A. Russ
Subject: Re: mapcar use.
Date: 
Message-ID: <ymik6bgaaze.fsf@sevak.isi.edu>
"lispuser" <·········@yahoo.co.in> writes:

> Hello all,
> I am trying to use the mapcar function for the multiplication of 2
> lists as :
> (1 2) and (4 5 6)
> so that the result which i get is
> as
> ((4 5 6) (8 10 12))
> I am still not gettin how to use eval and mapcar to achieve this...
> Can somebody help me...
> thanks

Well, you need to nest them, since you are not doing element-by-element
multiplication.  So, if you first tried the simple solution:

(mapcar #'* '(1 2) '(4 5 6))  =>  (4 10)

since the mapping is over the pairs of elements chosen from each list,
and constrained by the length of the shorter list.

(mapcar #'(lambda (factor) (mapcar #'(lambda (element) (* factor element))
                                   arguments))
        factors)

(mapcar #'(lambda (factor) (mapcar #'(lambda (element) (* factor element))
                                   '(4 5 6)))
        '(1 2))
  ==> ((4 5 6) (8 10 12))

-- 
Thomas A. Russ,  USC/Information Sciences Institute