From: Andreas Hinze
Subject: mapcar irritation
Date: 
Message-ID: <3u3ro2Fv0k6rU2@uni-berlin.de>
Hi all,
according to CLHS the result of mapcar is:
"The value returned by mapcar is a list of the results of successive 
calls to function."
(http://www.lispworks.com/documentation/HyperSpec/Body/f_mapc_.htm#mapcar)

So i would expect that

(mapcar #'(lambda (x) (values)) '(1 2 3))

should return () since (values) doesn't return anything.
But in CLISP and CMUCL i got (nil nil nil).

Can please anyone explain whats wrong with my thought ?

Kind regards
AHz

P.S: No, this is not a homework ;-)
      A.

From: Thomas F. Burdick
Subject: Re: mapcar irritation
Date: 
Message-ID: <xcvbr0jt6cb.fsf@conquest.OCF.Berkeley.EDU>
Andreas Hinze <···@snafu.de> writes:

> Hi all,
> according to CLHS the result of mapcar is:
> "The value returned by mapcar is a list of the results of successive
> calls to function."
> (http://www.lispworks.com/documentation/HyperSpec/Body/f_mapc_.htm#mapcar)
> 
> So i would expect that
> 
> (mapcar #'(lambda (x) (values)) '(1 2 3))
> 
> should return () since (values) doesn't return anything.
> But in CLISP and CMUCL i got (nil nil nil).
>
> Can please anyone explain whats wrong with my thought ?

It's already been explain what's wrong here, in CL.  It's a cute
misconception, though, and a perfectly legitimate Lisp could have the
result you're expecting.  CL supports multiple values, but generally
works in everything-has-one-value mode.  From a practical point of
view, you probably want to use MAPCAN:

  (mapcan (lambda (n) (when (evenp n) (list n n)))
          '(1 2 3 4 5 6))
  => (2 2 4 4 6 6)

> P.S: No, this is not a homework ;-)
>       A.

But since being upset with mapcar sounds like a newbie frustration, I
do have homework for you ;-)

How would you write a function called MAPCAR-VALUES that does what you
expected?

-- 
           /|_     .-----------------------.                        
         ,'  .\  / | Free Mumia Abu-Jamal! |
     ,--'    _,'   | Abolish the racist    |
    /       /      | death penalty!        |
   (   -.  |       `-----------------------'
   |     ) |                               
  (`-.  '--.)                              
   `. )----'                               
From: Andreas Hinze
Subject: Re: mapcar irritation
Date: 
Message-ID: <3u5v3nFvhrofU3@uni-berlin.de>
Hi,

Thomas F. Burdick wrote:
> 
> It's already been explain what's wrong here, in CL.  It's a cute
> misconception, though, and a perfectly legitimate Lisp could have the
And this misconception was my problem :-)

> result you're expecting.  CL supports multiple values, but generally
> works in everything-has-one-value mode.  From a practical point of
> view, you probably want to use MAPCAN:
> 
>   (mapcan (lambda (n) (when (evenp n) (list n n)))
>           '(1 2 3 4 5 6))
>   => (2 2 4 4 6 6)
> 
Unfortunally in the application nil is a possible result. Thats why
tried the (values) idea.

> 
>>P.S: No, this is not a homework ;-)
>>      A.
> 
> 
> But since being upset with mapcar sounds like a newbie frustration, I
> do have homework for you ;-)
Not upset, just a "minor engineering problem".
> 
> How would you write a function called MAPCAR-VALUES that does what you
> expected?
> 
Hows about (which indeed solved my problem):
(defun MAPCAR-VALUES (f l)
   (mapcan #'(lambda (x) (multiple-value-list (funcall f x))) l))

Any better solution is highly welcome. I.E. one that can handle list+
as arguments :-)

Kind regards
AHz
From: RPG
Subject: Re: mapcar irritation
Date: 
Message-ID: <1132336040.351116.31970@o13g2000cwo.googlegroups.com>
Andreas Hinze wrote:
[...snip...]
> Unfortunally in the application nil is a possible result. Thats why
> tried the (values) idea.

Well, that's really what multiple-values are for.  So if, e.g., you
want a boolean, but there's a possibility that the answer won't be
supplied, you can do something like

(defun maybe-a-boolean ()
   (if <there's an answer> (values t answer) nil))

and

(defun consume-a-possible-answer ()
   (multiple-value-bind (answer-p answer)
       (if answer-p
           (process answer)
           (handle-no-answer))))

Then you could loop or something to do what you want

(let ((collector nil))
(dolist (foo values collector)
  (multiple-value-bind (answer-p answer)
    (when answer-p (push answer collector))))

You could use mapcan if you prefer.

Unfortunately, because it's not well-adapted to multiple-values, this
is nasty in the LOOP macro...

cheers,
r
From: Geoffrey Summerhayes
Subject: Re: mapcar irritation
Date: 
Message-ID: <nVpff.4141$w84.782667@news20.bellglobal.com>
"Andreas Hinze" <···@snafu.de> wrote in message 
···················@uni-berlin.de...
>
> Hows about (which indeed solved my problem):
> (defun MAPCAR-VALUES (f l)
>   (mapcan #'(lambda (x) (multiple-value-list (funcall f x))) l))
>
> Any better solution is highly welcome. I.E. one that can handle list+
> as arguments :-)

(defun mapcar-values (fn &rest lists)
  (apply #'mapcar (lambda (&rest values)
                    (multiple-value-list (apply fn values)))

         lists))

because it gives a way to distinguish what came back from each call

CL-USER > (defun foo(x) (apply #'values (loop for i below x collecting 
nil)))
FOO

CL-USER > (mapcar-values #'foo '(0 1 2 3))
(NIL (NIL) (NIL NIL) (NIL NIL NIL))

and get the list with

CL-USER > (apply #'append (mapcar-values #'foo '(0 1 2 3)))
(NIL NIL NIL NIL NIL NIL)

--
Geoff
From: Thomas F. Burdick
Subject: Re: mapcar irritation
Date: 
Message-ID: <xcvveyproms.fsf@conquest.OCF.Berkeley.EDU>
Andreas Hinze <···@snafu.de> writes:

> Thomas F. Burdick wrote:
>
> > How would you write a function called MAPCAR-VALUES that does what
> > you
> > expected?
>
> Hows about (which indeed solved my problem):
>
> (defun MAPCAR-VALUES (f l)
>    (mapcan #'(lambda (x) (multiple-value-list (funcall f x))) l))
> 
> Any better solution is highly welcome. I.E. one that can handle list+
> as arguments :-)

Almost :-)

If you use &REST arguments and APPLY you'll be there.

-- 
           /|_     .-----------------------.                        
         ,'  .\  / | Free Mumia Abu-Jamal! |
     ,--'    _,'   | Abolish the racist    |
    /       /      | death penalty!        |
   (   -.  |       `-----------------------'
   |     ) |                               
  (`-.  '--.)                              
   `. )----'                               
From: Ron Garret
Subject: Re: mapcar irritation
Date: 
Message-ID: <rNOSPAMon-CE3597.07361919112005@news.gha.chartermi.net>
In article <···············@conquest.OCF.Berkeley.EDU>,
 ···@conquest.OCF.Berkeley.EDU (Thomas F. Burdick) wrote:

> Andreas Hinze <···@snafu.de> writes:
> 
> > Thomas F. Burdick wrote:
> >
> > > How would you write a function called MAPCAR-VALUES that does what
> > > you
> > > expected?
> >
> > Hows about (which indeed solved my problem):
> >
> > (defun MAPCAR-VALUES (f l)
> >    (mapcan #'(lambda (x) (multiple-value-list (funcall f x))) l))
> > 
> > Any better solution is highly welcome. I.E. one that can handle list+
> > as arguments :-)
> 
> Almost :-)
> 
> If you use &REST arguments and APPLY you'll be there.

Or (from my utils file):

;;;  MAP-EXTEND works like mapcar except that its termination condition 
is when all
;;;  of its argument lists are nil.
(defun map-extend (fn &rest lists)
  (if (every #'null lists)
    nil
    (cons (apply fn (mapcar #'car lists))
          (apply #'map-extend fn (mapcar #'cdr lists)))))

;;;  MMAP is a generalized version of MAP for mapping functions which 
return
;;;  multiple values.
(defun mmap (fn &rest lists)
  (if (some #'null lists)
    nil
    (let* ( (cars (multiple-value-list (apply fn (mapcar #'car lists))))
            (cdrs (multiple-value-list (apply #'mmap fn (mapcar #'cdr 
lists)))) )
      (apply #'values (map-extend #'cons cars cdrs)))))

rg
From: Andreas Hinze
Subject: Re: mapcar irritation
Date: 
Message-ID: <3udjefF10qluvU1@uni-berlin.de>
Hi all,

Ron Garret wrote:
> In article <···············@conquest.OCF.Berkeley.EDU>,
>  ···@conquest.OCF.Berkeley.EDU (Thomas F. Burdick) wrote:
> 
> 
>>Andreas Hinze <···@snafu.de> writes:
>>
>>
>>>Thomas F. Burdick wrote:
>>>
>>>
>>>>How would you write a function called MAPCAR-VALUES that does what
>>>>you
>>>>expected?
>>>
>>>Hows about (which indeed solved my problem):
>>>
>>>(defun MAPCAR-VALUES (f l)
>>>   (mapcan #'(lambda (x) (multiple-value-list (funcall f x))) l))
>>>
>>>Any better solution is highly welcome. I.E. one that can handle list+
>>>as arguments :-)
>>
>>Almost :-)
>>
>>If you use &REST arguments and APPLY you'll be there.
> 
> 
> Or (from my utils file):
> 
> ;;;  MAP-EXTEND works like mapcar except that its termination condition 
> is when all
> ;;;  of its argument lists are nil.
> (defun map-extend (fn &rest lists)
>   (if (every #'null lists)
>     nil
>     (cons (apply fn (mapcar #'car lists))
>           (apply #'map-extend fn (mapcar #'cdr lists)))))
> 
> ;;;  MMAP is a generalized version of MAP for mapping functions which 
> return
> ;;;  multiple values.
> (defun mmap (fn &rest lists)
>   (if (some #'null lists)
>     nil
>     (let* ( (cars (multiple-value-list (apply fn (mapcar #'car lists))))
>             (cdrs (multiple-value-list (apply #'mmap fn (mapcar #'cdr 
> lists)))) )
>       (apply #'values (map-extend #'cons cars cdrs)))))
> 
> rg

Now i have a whole bunch of solutions :-)
Thanks to all for helping

Kind regards
AHz
From: Marco Antoniotti
Subject: Re: mapcar irritation
Date: 
Message-ID: <DY2ff.86$pa3.27076@typhoon.nyu.edu>
Andreas Hinze wrote:
> Hi all,
> according to CLHS the result of mapcar is:
> "The value returned by mapcar is a list of the results of successive 
> calls to function."
> (http://www.lispworks.com/documentation/HyperSpec/Body/f_mapc_.htm#mapcar)
> 
> So i would expect that
> 
> (mapcar #'(lambda (x) (values)) '(1 2 3))
> 
> should return () since (values) doesn't return anything.
> But in CLISP and CMUCL i got (nil nil nil).
> 
> Can please anyone explain whats wrong with my thought ?

I think I remember reading somewhere in the CLHS that when used in a 
"valued" context, (values) is interpreted as NIL.  Hence your result.

Cheers
--
Marco
From: Kaz Kylheku
Subject: Re: mapcar irritation
Date: 
Message-ID: <1132268743.826719.227100@o13g2000cwo.googlegroups.com>
Andreas Hinze wrote:
> Hi all,
> according to CLHS the result of mapcar is:
> "The value returned by mapcar is a list of the results of successive
> calls to function."
> (http://www.lispworks.com/documentation/HyperSpec/Body/f_mapc_.htm#mapcar)
>
> So i would expect that
>
> (mapcar #'(lambda (x) (values)) '(1 2 3))
>
> should return () since (values) doesn't return anything.
> But in CLISP and CMUCL i got (nil nil nil).

What happens is that when a function returns fewer values than are
expected in some contexts, the situation is handled by padding the
missing information with NIL.

For instance:

  (multiple-value-bind (a b c) (values 1 2) ...)

will set up A and B with 1 and 2 respectively. It's not an error
condition that a third value is bound but not supplied. Rather, C gets
NIL.

Likewise it's also not an error condition when some extra values are
ignored.


You can regard this behavior of MULTIPLE-VALUE-BIND as being a general
principle that applies in situations where the retrieval of the
returned value is implicit. E.g.

  (cons (values) (values))
  -> (NIL)

What should happen here? (VALUES) is evaluated in a context where a
value (exactly one) is expected, so the value NIL is substituted. Thus
(cons nil nil) gets called.

If you want to write code that is sensitive to the number of values
returned, you have to use MULTIPLE-VALUE-LIST or maybe
MULTIPLE-VALUE-CALL. With these operators, you can tell whether NIL was
returned, or whether no values were returned:

  (multiple-value-list (values)) -> NIL
  (multiple-value-list nil) -> (NIL)

For instance, if you were writing your own REPL that shows the user all
of the returned values properly, you would actually write a REMVLPL:
read, eval, multiple-value-list, print loop. A naively written REP,
doing, literally, (PRINT (EVAL ...))), would incorrectly show that
(values) produces NIL, and that (values 1 2) produces 1.

You could write a version of MAPCAR which uses MULTIPLE-VALUE-LIST to
capture all of the values of the function, and then NCONC-s the lists
together. Then (VALUES) could be used to indicate nothing. But then,
you might as well just return lists from the function, and use MAPCON!
If all you do with multiple values is cons them into a list, you don't
gain anything by using them.
From: Andreas Hinze
Subject: Re: mapcar irritation
Date: 
Message-ID: <3u5v2fFvhrofU2@uni-berlin.de>
Hi,

Kaz Kylheku wrote:
> 
> If you want to write code that is sensitive to the number of values
> returned, you have to use MULTIPLE-VALUE-LIST or maybe
> MULTIPLE-VALUE-CALL. With these operators, you can tell whether NIL was
> returned, or whether no values were returned:
> 
>   (multiple-value-list (values)) -> NIL
>   (multiple-value-list nil) -> (NIL)
> 
Good hint, Thanks. I made a solution to my problem with this.

Kind regards
AHz
From: Kenny Tilton
Subject: Re: mapcar irritation
Date: 
Message-ID: <Xg3ff.31779$u43.21971@twister.nyc.rr.com>
Andreas Hinze wrote:
> Hi all,
> according to CLHS the result of mapcar is:
> "The value returned by mapcar is a list of the results of successive 
> calls to function."
> (http://www.lispworks.com/documentation/HyperSpec/Body/f_mapc_.htm#mapcar)
> 
> So i would expect that
> 
> (mapcar #'(lambda (x) (values)) '(1 2 3))
> 
> should return () since (values) doesn't return anything.
> But in CLISP and CMUCL i got (nil nil nil).
> 
> Can please anyone explain whats wrong with my thought ?

Your thinking is probably just too quick and imprecise, because the 
result is perfectly consistent with the description.

"The value returned ... is a list of the results of ... calls to the 
function."

There are three calls to be made in your example, so you are going to 
get a list of three... what?

If you poke around the Lisp doc a little you will discover that, where 
the caller needs a value and the callee terminates with (values), the 
caller gets a NIL instead of collapsing in a heap. Try:

    (list (values)(values)(values))

And if your Lisp is really weak, try:

    (list nil nil nil)

...just to make sure you understand that much.

So your example makes a list of the results of three calls to a function 
ending with (values), and you get (nil nil nil) because mapcar is trying 
to use a value returned by the function.


-- 
Kenny

Why Lisp? http://wiki.alu.org/RtL_Highlight_Film

"I've wrestled with reality for 35 years, Doctor, and I'm happy to state 
I finally won out over it."
     Elwood P. Dowd, "Harvey", 1950
From: Pascal Bourguignon
Subject: Re: mapcar irritation
Date: 
Message-ID: <87acg36k9n.fsf@thalassa.informatimago.com>
Kenny Tilton <·······@nyc.rr.com> writes:

> Andreas Hinze wrote:
>> Hi all,
>> according to CLHS the result of mapcar is:
>> "The value returned by mapcar is a list of the results of successive
>> calls to function."
>> (http://www.lispworks.com/documentation/HyperSpec/Body/f_mapc_.htm#mapcar)
>> So i would expect that
>> (mapcar #'(lambda (x) (values)) '(1 2 3))
>> should return () since (values) doesn't return anything.
>> But in CLISP and CMUCL i got (nil nil nil).
>> Can please anyone explain whats wrong with my thought ?
> [...]
> If you poke around the Lisp doc a little you will discover that, where
> the caller needs a value and the callee terminates with (values), the
> caller gets a NIL instead of collapsing in a heap. Try:
>
>     (list (values)(values)(values))
> [...]

Note that the NILs don't come from (values), which indeed returns 0
values, but from the call site: when you expect more values than a
function returns, you get NIL for the missing values:

(multiple-value-bind (a b c d) (values 1 2) (list a b c d)) --> (1 2 NIL NIL)

The NILs are not produced by (values 1 2), but by assigning a non
existent value to c and d.

The same occurs with only one value: 

   (setf a (values)) --> NIL
   (values)          -->        ; no value


-- 
"This machine is a piece of GAGH!  I need dual Opteron 850
processors if I am to do battle with this code!"
From: Andreas Hinze
Subject: Re: mapcar irritation
Date: 
Message-ID: <3u5udcFvl05pU1@uni-berlin.de>
Pascal Bourguignon wrote:
> Kenny Tilton <·······@nyc.rr.com> writes:
> 
> 
>>Andreas Hinze wrote:
>>
>>>Hi all,
>>>according to CLHS the result of mapcar is:
>>>"The value returned by mapcar is a list of the results of successive
>>>calls to function."
>>>(http://www.lispworks.com/documentation/HyperSpec/Body/f_mapc_.htm#mapcar)
>>>So i would expect that
>>>(mapcar #'(lambda (x) (values)) '(1 2 3))
>>>should return () since (values) doesn't return anything.
>>>But in CLISP and CMUCL i got (nil nil nil).
>>>Can please anyone explain whats wrong with my thought ?
>>
>>[...]
>>If you poke around the Lisp doc a little you will discover that, where
>>the caller needs a value and the callee terminates with (values), the
>>caller gets a NIL instead of collapsing in a heap. Try:
>>
>>    (list (values)(values)(values))
>>[...]
> 
> 
> Note that the NILs don't come from (values), which indeed returns 0
> values, but from the call site: when you expect more values than a
> function returns, you get NIL for the missing values:
> 
Indeed. But didn't this imply that mapcar IS missing a value as a result
of the function call. And then, is this what CLHS says ? I read it
the other way around and would expect that mapcar return what it get, if it
get anything from a particular function call.

Kind regards
AHz
From: Pascal Bourguignon
Subject: Re: mapcar irritation
Date: 
Message-ID: <87fypu57xp.fsf@thalassa.informatimago.com>
Andreas Hinze <···@snafu.de> writes:
>> Note that the NILs don't come from (values), which indeed returns 0
>> values, but from the call site: when you expect more values than a
>> function returns, you get NIL for the missing values:
>> 
> Indeed. But didn't this imply that mapcar IS missing a value as a result
> of the function call. And then, is this what CLHS says ? I read it
> the other way around and would expect that mapcar return what it get, if it
> get anything from a particular function call.

mapcar expects exactly _one_ value from each function calls.

(mapcar (lambda (x) (values 1 2 3)) '(a b c)) --> (1 1 1)

-- 
"Specifications are for the weak and timid!"
From: David Steuber
Subject: Re: mapcar irritation
Date: 
Message-ID: <87lkzklxuf.fsf@david-steuber.com>
Pascal Bourguignon <····@mouse-potato.com> writes:

> mapcar expects exactly _one_ value from each function calls.
> 
> (mapcar (lambda (x) (values 1 2 3)) '(a b c)) --> (1 1 1)

Don't you mean exactly _one_ value per list?

(mapcar (lambda (x y) (list x y)) '(a b c) '(1 2 3)) 
  --> ((a 1) (b 2) (c 3))

-- 
http://www.david-steuber.com/
The UnBlog: An island of conformity in a sea of quirks.
http://www.david-steuber.com/snippets/Boycott_Sony/
From: Pascal Bourguignon
Subject: Re: mapcar irritation
Date: 
Message-ID: <8764qo4une.fsf@thalassa.informatimago.com>
David Steuber <·····@david-steuber.com> writes:

> Pascal Bourguignon <····@mouse-potato.com> writes:
>
>> mapcar expects exactly _one_ value from each function calls.
>> 
>> (mapcar (lambda (x) (values 1 2 3)) '(a b c)) --> (1 1 1)
>
> Don't you mean exactly _one_ value per list?

No I meant what I meant.  We're not discussing lists, we're discussing
multiple vaules.

> (mapcar (lambda (x y) (list x y)) '(a b c) '(1 2 3)) 
>   --> ((a 1) (b 2) (c 3))

(mapcar (lambda (x y) (values x y)) '(a b c) '(1 2 3))  
    --> (A B C)


-- 
__Pascal Bourguignon__                     http://www.informatimago.com/
Until real software engineering is developed, the next best practice
is to develop with a dynamic system that has extreme late binding in
all aspects. The first system to really do this in an important way
is Lisp. -- Alan Kay
From: David Steuber
Subject: Re: mapcar irritation
Date: 
Message-ID: <874q68ln1r.fsf@david-steuber.com>
Pascal Bourguignon <····@mouse-potato.com> writes:

> David Steuber <·····@david-steuber.com> writes:
> 
> > Pascal Bourguignon <····@mouse-potato.com> writes:
> >
> >> mapcar expects exactly _one_ value from each function calls.
> >> 
> >> (mapcar (lambda (x) (values 1 2 3)) '(a b c)) --> (1 1 1)
> >
> > Don't you mean exactly _one_ value per list?
> 
> No I meant what I meant.  We're not discussing lists, we're discussing
> multiple vaules.
> 
> > (mapcar (lambda (x y) (list x y)) '(a b c) '(1 2 3)) 
> >   --> ((a 1) (b 2) (c 3))
> 
> (mapcar (lambda (x y) (values x y)) '(a b c) '(1 2 3))  
>     --> (A B C)

OK, I misread that.

-- 
http://www.david-steuber.com/
The UnBlog: An island of conformity in a sea of quirks.
http://www.david-steuber.com/snippets/Boycott_Sony/
From: Wade Humeniuk
Subject: Re: mapcar irritation
Date: 
Message-ID: <%J7ff.148407$Io.78594@clgrps13>
Andreas Hinze wrote:
> Hi all,
> according to CLHS the result of mapcar is:
> "The value returned by mapcar is a list of the results of successive 
> calls to function."
> (http://www.lispworks.com/documentation/HyperSpec/Body/f_mapc_.htm#mapcar)
> 
> So i would expect that
> 
> (mapcar #'(lambda (x) (values)) '(1 2 3))
> 
> should return () since (values) doesn't return anything.
> But in CLISP and CMUCL i got (nil nil nil).
> 
> Can please anyone explain whats wrong with my thought ?
> 
> Kind regards
> AHz
> 
> P.S: No, this is not a homework ;-)
>      A.
> 

Its the same reason that..

CL-USER 2 > (loop repeat 3 collect (values))
(NIL NIL NIL)

CL-USER 3 >

Ya gotta collect something.

If you need to something like the above, do

CL-USER 3 > (mapcan (lambda (x) (values)) '(1 2 3))
NIL

CL-USER 4 >

Wade