Re: I still don't get MAPCAN
- From: Pascal Bourguignon <pjb@xxxxxxxxxxxxxxxxx>
- Date: Thu, 17 Aug 2006 18:16:22 +0200
"jmckitrick" <j_mckitrick@xxxxxxxxx> writes:
Bill Atkins wrote:
Do those lists look the same to you? They look like pretty different
results to me.
The CLHS, believe it or not, is very helpful here:
"mapcan and mapcon are like mapcar and maplist respectively, except
that the results of applying function are combined into a list by the
use of nconc rather than list."
See the part about NCONC'ing the return values together? Funny what
you can find in the spec.
It's not the literal effect I don't understand. It's if MAPCAN is
supposed to be the corresponding 'destructive' version of MAPCAR,
unless these two are not complimentary in that way.
Example:
CL-USER> (nconc '(1 2 3) '(4 5 6))
(1 2 3 4 5 6)
CL-USER> (append '(1 2 3) '(4 5 6))
(1 2 3 4 5 6)
CL-USER>
These produce the same result, but with different side effects. I
thought MAPCAR and MAPCAN had the same relationship, but that cannot
be, if the results are different.
Apparently, though, MAPCAN is not just a 'destructive' version of
MAPCAR. That's what I was trying to clarify.
Just ask it! ;-)
(setf *print-circle* t)
(let ((as (list 'one 'two 'three))
(bs (list 'un 'deux 'trois))
(cared-objects '())
(caned-objects '()))
(let ((mapcar-result (mapcar (lambda (a b)
(let ((object (list a b)))
(push object cared-objects)
object))
as bs))
(mapcan-result (mapcan (lambda (a b)
(let ((object (list a b)))
(push object caned-objects)
object))
as bs)))
(setf cared-objects (nreverse cared-objects)
caned-objects (nreverse caned-objects))
(list
`(as ,as)
`(bs ,bs)
`(cared-objects ,cared-objects)
`(mapcar-result ,mapcar-result)
`(caned-objects ,caned-objects)
`(mapcan-result ,mapcan-result))))
-->
((AS (ONE TWO THREE))
(BS (UN DEUX TROIS))
(CARED-OBJECTS (#1=(ONE UN) #2=(TWO DEUX) #3=(THREE TROIS)))
(MAPCAR-RESULT (#1# #2# #3#))
(CANED-OBJECTS (#4=(ONE UN . #5=(TWO DEUX . #6=(THREE TROIS))) #5# #6#))
(MAPCAN-RESULT #4#))
With *print-circle*, any non-symbol object that appears several times
in the s-expr is first identified with #N= and then referenced with
#N#. You can then see where the same CONS cell is referenced twice
(or more). (interned symbols printed identically are identical by
definition, so there's no need to number them).
In the mapcar part, you see that each of the objects returned by the
lambda #1#, #2# and #3# are collected in a new list created and
returned by mapcar (no other references to the CONS cells of this list
exist anywhere else).
In the mapcan part, on the contrary you see that the CONS cells of the
list returned by mapcan are actually the CONS cells returned by the
lambda.
The first object put on the caned-objects list was #4=(ONE . (UN . NIL))
The second object put on the caned-objects list was #5=(TWO . (DEUX . NIL))
When this second object was returned by the lambda, MAPCAN modified
the CDR of the LAST cell of the first object #4#, doing something like:
(setf (cdr (last #4#)) #5#)
Hence, now you see that #4# include #5#:
#4=(ONE . (UN . #5=(TWO . (DEUX . NIL))))
The third object put on the caned-object list was #6#, and when
returned, has been assigned by MAPCAN to the CDR of the new LAST
cell, of the object #5#:
(setf (cdr (last #4#)) #6#)
Hence, now you see that #4# include #5#:
#4=(ONE . (UN . #5=(TWO . (DEUX . #6=(THREE . (TROIS . NIL))))))
or:
#4=(ONE UN . #5=(TWO DEUX . #6=(THREE TROIS)))
as the printer puts it. Finally, this is this list that is returned
by MAPCAN. MAPCAN didn't CONS any list. It modified the lists it got
from the lambda, and concatenated them into one big list.
Exercise: draw a diagram of boxes and arrows representing the whole result:
((AS (ONE TWO THREE))
(BS (UN DEUX TROIS))
(CARED-OBJECTS (#1=(ONE UN) #2=(TWO DEUX) #3=(THREE TROIS)))
(MAPCAR-RESULT (#1# #2# #3#))
(CANED-OBJECTS (#4=(ONE UN . #5=(TWO DEUX . #6=(THREE TROIS))) #5# #6#))
(MAPCAN-RESULT #4#))
--
__Pascal Bourguignon__ http://www.informatimago.com/
"You can tell the Lisp programmers. They have pockets full of punch
cards with close parentheses on them." --> http://tinyurl.com/8ubpf
.
- References:
- I still don't get MAPCAN
- From: jmckitrick
- Re: I still don't get MAPCAN
- From: Bill Atkins
- Re: I still don't get MAPCAN
- From: jmckitrick
- I still don't get MAPCAN
- Prev by Date: Re: is it effective/better
- Next by Date: Re: Erlang brings up interesting questions about Lisp
- Previous by thread: Re: I still don't get MAPCAN
- Next by thread: Re: I still don't get MAPCAN
- Index(es):
Relevant Pages
|