From: cartercc
Subject: Question about behavior of apply
Date: 
Message-ID: <eed5ae01-cec9-4e16-a3bd-91ca23cced45@o40g2000prn.googlegroups.com>
Here is the session:

CL-USER> (setq lst '((a b c) (d e f) (g h i)))
((A B C) (D E F) (G H I))
CL-USER> (mapcar 'list lst)
(((A B C)) ((D E F)) ((G H I)))
CL-USER> (apply 'mapcar 'list lst)
((A D G) (B E H) (C F I))

I set lst to a list of three lists: ((a b c) (d e f) (g h i))
I call mapcar with the function list on lst and it returns lst wrapped
in a list.
Then, I apply mapcar the same way, and it not only does not wrap lst
in a list, but it also scrambles the list.

Why? I understand that mapcar takes the car of each list passed to it,
and I understand that lst is on list, not three lists. I just don't
understand why the behavior of mapcar would be changed by apply. Or
maybe that the behavior of list is changed by apply.

Thanks, CC.

From: ······@corporate-world.lisp.de
Subject: Re: Question about behavior of apply
Date: 
Message-ID: <8880e5ad-cd8f-4c53-a447-dcda05ad0bd1@r10g2000prf.googlegroups.com>
On 8 Jan., 20:07, cartercc <········@gmail.com> wrote:
> Here is the session:
>
> CL-USER> (setq lst '((a b c) (d e f) (g h i)))
> ((A B C) (D E F) (G H I))
> CL-USER> (mapcar 'list lst)
> (((A B C)) ((D E F)) ((G H I)))
> CL-USER> (apply 'mapcar 'list lst)
> ((A D G) (B E H) (C F I))
>
> I set lst to a list of three lists: ((a b c) (d e f) (g h i))
> I call mapcar with the function list on lst and it returns lst wrapped
> in a list.
> Then, I apply mapcar the same way, and it not only does not wrap lst
> in a list, but it also scrambles the list.
>
> Why? I understand that mapcar takes the car of each list passed to it,
> and I understand that lst is on list, not three lists. I just don't
> understand why the behavior of mapcar would be changed by apply. Or
> maybe that the behavior of list is changed by apply.
>
> Thanks, CC.

MAPCAR is     mapcar function &rest lists+ => result-list


So:


(apply 'mapcar 'list lst)

is like

(apply 'mapcar 'list '((a b c) (d e f) (g h i)))

is like

(mapcar 'list '(a b c)
              '(d e f)
              '(g h i))

Note that it maps over three lists.


Compare that to FUNCALL:

(funcall 'mapcar 'list lst)

is like

(funcall 'mapcar 'list '((a b c) (d e f) (g h i)))

is like

(mapcar 'list '((a b c) (d e f) (g h i)))

Note that it maps over one list.
From: Pascal J. Bourguignon
Subject: Re: Question about behavior of apply
Date: 
Message-ID: <87ocyhba8j.fsf@informatimago.com>
cartercc <········@gmail.com> writes:

> Here is the session:
>
> CL-USER> (setq lst '((a b c) (d e f) (g h i)))
> ((A B C) (D E F) (G H I))
> CL-USER> (mapcar 'list lst)
> (((A B C)) ((D E F)) ((G H I)))
> CL-USER> (apply 'mapcar 'list lst)
> ((A D G) (B E H) (C F I))
>
> I set lst to a list of three lists: ((a b c) (d e f) (g h i))
> I call mapcar with the function list on lst and it returns lst wrapped
> in a list.

No.  It returns a list containing each of the element of lst themselves
wrapped in a list.

> Then, I apply mapcar the same way, and it not only does not wrap lst
> in a list, but it also scrambles the list.

It works perfectly well, see joswig's answer.

(defun transpose (matrix)   (apply (function mapcar) (function list) matrix))
(defun zip   (list-of-list) (apply (function mapcar) (function list) list-of-list))
(defun unzip (list-of-list) (apply (function mapcar) (function list) list-of-list))

> Why? I understand that mapcar takes the car of each list passed to it,
> and I understand that lst is on list, not three lists. I just don't
> understand why the behavior of mapcar would be changed by apply. Or
> maybe that the behavior of list is changed by apply.

APPLY is a fundamental primitive of Lisp.  
It allows to transform a list of data into a list of arguments to a
function call.

   (apply (function +) (list 1 2 3 4)) == (+ 1 2 3 4)


FUNCALL cannot do that. (You can implement FUNCALL with APPLY, but you
cannot implement APPLY with FUNCALL).
-- 
__Pascal Bourguignon__
From: Kaz Kylheku
Subject: Re: Question about behavior of apply
Date: 
Message-ID: <20090114223412.536@gmail.com>
On 2009-01-08, cartercc <········@gmail.com> wrote:
> Here is the session:
>
> CL-USER> (setq lst '((a b c) (d e f) (g h i)))
> ((A B C) (D E F) (G H I))
> CL-USER> (mapcar 'list lst)
> (((A B C)) ((D E F)) ((G H I)))
> CL-USER> (apply 'mapcar 'list lst)
> ((A D G) (B E H) (C F I))
>
> I set lst to a list of three lists: ((a b c) (d e f) (g h i))
> I call mapcar with the function list on lst and it returns lst wrapped
> in a list.
> Then, I apply mapcar the same way, and it not only does not wrap lst
> in a list, but it also scrambles the list.

It's not scrambling but transposing it! You've reinvented the famous
Lisp trick for transposing a list-based matrix.

Think of the ((a b c) (d e f) (g h i)) as being the matrix

[ a b c ]
| d e f |
[ g h i ]

The transpose flips the matrix around its diagonal, turning
rows into columns and columns into rows.

> Why? I understand that mapcar takes the car of each list passed to it,
> and I understand that lst is on list, not three lists. I just don't
> understand why the behavior of mapcar would be changed by apply. 

Hint: MAPCAR is a variadic function; it can take more than one list.
(mapcar 'list lst) is like (funcall 'mapcar 'list lst),
which is very different from (apply 'mapcar 'list lst).

APPLY will crack open the list LST, and turn each of its elements
into a separate function call argument to pass to MAPCAR.
So MAPCAR is now no longer working with a single list-of-lists
but three individual lists.