From: Vladimir Zolotykh
Subject: mapcar
Date: 
Message-ID: <3C034AC3.307C21EB@eurocom.od.ua>
Would you mind to explain the following example from CLHS 
(Section 1.4.1.5 Designators) in more detail ?

(defun add-some (x)
  (defun add-some (x) (+ x 2))
  (+ x 1))

(mapcar 'add-some '(1 2 3 4))

I can't catch in which case this might produce (2 3 4 5) and why.

-- 
Vladimir Zolotykh                         ······@eurocom.od.ua

From: Kent M Pitman
Subject: Re: mapcar
Date: 
Message-ID: <sfw1yikmuiv.fsf@shell01.TheWorld.com>
Vladimir Zolotykh <······@eurocom.od.ua> writes:

> Would you mind to explain the following example from CLHS 
> (Section 1.4.1.5 Designators) in more detail ?
> 
> (defun add-some (x)
>   (defun add-some (x) (+ x 2))
>   (+ x 1))
> 
> (mapcar 'add-some '(1 2 3 4))
> 
> I can't catch in which case this might produce (2 3 4 5) and why.

The definition of ADD-SOME done by the inner DEFUN is global, not local.

If MAPCAR funcalls the symbol ADD-SOME, then the second time it does, it
will see the new definition, (lambda (x) (+ x 2)), of ADD-SOME.  But if 
it instead coercses ADD-SOME to a function and holds that coerced value 
in a local variable, applying that, it will always see the definition
that was current at the time MAPCAR was entered, not any updated definition
of ADD-SOME on subsequent list elements, since it won't re-fetch the value
every time.
From: Vassil Nikolov
Subject: Re: mapcar
Date: 
Message-ID: <f34a0f4f.0111281743.165b8713@posting.google.com>
Kent M Pitman <······@world.std.com> wrote in message news:<···············@shell01.TheWorld.com>...
> Vladimir Zolotykh <······@eurocom.od.ua> writes:
[...]
> > (defun add-some (x)
> >   (defun add-some (x) (+ x 2))
> >   (+ x 1))
> > 
> > (mapcar 'add-some '(1 2 3 4))
[...]
> If MAPCAR funcalls the symbol ADD-SOME, then the second time it does, it
> will see the new definition, (lambda (x) (+ x 2)), of ADD-SOME.  But if 
> it instead coercses ADD-SOME to a function and holds that coerced value 
> in a local variable, applying that, it will always see the definition
> that was current at the time MAPCAR was entered, not any updated definition
> of ADD-SOME on subsequent list elements, since it won't re-fetch the value
> every time.

The distinction between these two approaches becomes more interesting if
we imagine an autoloaded function in ADD-SOME's place.

(Autoloading, of course, is not a standard Common Lisp feature, but many
implementations provide it.)

Another reason why holding a coerced function value might be undesirable
is that it would be inconsistent with any NOTINLINE declarations.  (Note
that I am not saying that MAPCAR can know about such.)

--- Vassil.
From: Kent M Pitman
Subject: Re: mapcar
Date: 
Message-ID: <sfwzo56nx8a.fsf@shell01.TheWorld.com>
··········@poboxes.com (Vassil Nikolov) writes:

> Another reason why holding a coerced function value might be undesirable
> is that it would be inconsistent with any NOTINLINE declarations.  (Note
> that I am not saying that MAPCAR can know about such.)

This statement, or at least the part before the parens, seems to as
much as say that
 (locally (declare (inline f))
   (symbol-function 'f))
should signal an error.  If so, I don't agree.  (MAPCAR 'F ...) is passing
symbol data, well outside the realm of an inline declaration. 
From: Vassil Nikolov
Subject: Re: mapcar
Date: 
Message-ID: <u8zcq44jo.fsf@eskimo.com>
    On Thu, 29 Nov 2001 02:10:13 GMT, Kent M Pitman <······@world.std.com> said:

    Kent> ··········@poboxes.com (Vassil Nikolov) writes:
    Vassil> Another reason why holding a coerced function value might be undesirable
    Vassil> is that it would be inconsistent with any NOTINLINE declarations.  (Note
    Vassil> that I am not saying that MAPCAR can know about such.)

    Kent> This statement, or at least the part before the parens, seems to as
    Kent> much as say that
    Kent>  (locally (declare (inline f))
    Kent>    (symbol-function 'f))
    Kent> should signal an error.  If so, I don't agree.  (MAPCAR 'F ...) is passing
    Kent> symbol data, well outside the realm of an inline declaration. 

If the first of my sentences quoted above seems to say that such an
error should be signalled, then that was bad wording on my part.  I
used `inconsistent' not to refer to a breach of the rules of legal
behavior, but to a discrepancy between what a programmer might want
and what the implementation might provide.  Of course NOTINLINE and
INLINE declarations (of which I mentioned only the former) cannot
affect the way MAPCAR obtains the function to call---MAPCAR doesn't
know (cannot know) about them.

In other words, I had this in mind.  An implementor of MAPCAR needs
to decide, among other things, whether to coerce the function
designator (A) once, or (B) at every call (both legal).  (A) might
clash with the programmer's possible desire to use function
redefinition on the fly (when a NOTINLINE declaration would be
expected); (B) might clash with the possible desire to make the
calls faster (when an INLINE declaration might be present).
I.e. there is an analogy between the former and disobeying a
NOTINLINE declaration (illegal), and between the latter and
ignoring an INLINE declaration (legal).  Thus there are cases for
both (A) and (B) when they do not match what the programmer wants,
but with (B) the consequences are less `harmful' (more in the
spirit of the language, so to say).

(I wish I had more time and a better writing ability to make the
above explanation more concise...)

---Vassil.
From: Dr. Edmund Weitz
Subject: Re: mapcar
Date: 
Message-ID: <m3d724wqce.fsf@bird.agharta.de>
Vladimir Zolotykh <······@eurocom.od.ua> writes:

> Would you mind to explain the following example from CLHS 
> (Section 1.4.1.5 Designators) in more detail ?
> 
> (defun add-some (x)
>   (defun add-some (x) (+ x 2))
>   (+ x 1))
> 
> (mapcar 'add-some '(1 2 3 4))
> 
> I can't catch in which case this might produce (2 3 4 5) and why.
> 
> -- 
> Vladimir Zolotykh                         ······@eurocom.od.ua

As far as I understand this, it would be OK for a conforming
implementation to treat the above call to MAPCAR as if it had been

  (mapcar #'add-some '(1 2 3 4))

instead, thus optimizing away the need to look up the functional value
of the symbol ADD-SOME for each element of the list. This would indeed
result in (2 3 4 5), but none of CMUCL, SBCL, CLISP, ACL, LispWorks,
or ECLS seems to do this.

Edi.