Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Illegal function object

262 views
Skip to first unread message

joachim de beule

unread,
Mar 16, 1999, 3:00:00 AM3/16/99
to
If this allready appeared then please ignore it.

Can anyone tell my why

(funcall #'(lambda (x) (+ x 1)) 0)

evaluates to 1 as it should but

(setf test '((lambda (x) (+ x 1))))
(funcall (first test) 0)

returns the error

Error: Illegal function object: #'(LAMBDA (X) (+ X 1))

Thanks.
--
Joachim De Beule,
tel: +32 9 2646541
email: joa...@inwpent3.rug.ac.be

Fernando D. Mato Mira

unread,
Mar 16, 1999, 3:00:00 AM3/16/99
to

joachim de beule wrote:

> (setf test '((lambda (x) (+ x 1))))
> (funcall (first test) 0)
>
> returns the error
>
> Error: Illegal function object: #'(LAMBDA (X) (+ X 1))
>

That should be

(setf test `(,(lambda (x) (+ x 1))))

Regards,

--
Fernando D. Mato Mira
Real-Time SW Eng & Networking
Advanced Systems Engineering Division
CSEM
Jaquet-Droz 1 email: matomira AT acm DOT org
CH-2007 Neuchatel tel: +41 (32) 720-5157
Switzerland FAX: +41 (32) 720-5720

www.csem.ch www.vrai.com ligwww.epfl.ch/matomira.html

joachim de beule

unread,
Mar 16, 1999, 3:00:00 AM3/16/99
to
joachim de beule <joa...@inwpent3.rug.ac.be> writes:

> If this allready appeared then please ignore it.
>
> Can anyone tell my why
>
> (funcall #'(lambda (x) (+ x 1)) 0)
>
> evaluates to 1 as it should but
>

> (setf test '((lambda (x) (+ x 1))))
> (funcall (first test) 0)
>
> returns the error
>
> Error: Illegal function object: #'(LAMBDA (X) (+ X 1))
>

Actually, it does not return an error, but this solution
to my problem is a typing error by myself. I Actually
wanted to write

(setf test '(#'(lambda (x) (+ x 1))))
(funcall (first test) 0)

which produces the error.

Nevertheless, why is that the case ? Is there some fundamental
justification for it ?

Fernando D. Mato Mira

unread,
Mar 16, 1999, 3:00:00 AM3/16/99
to

"Fernando D. Mato Mira" wrote:

> That should be
>
> (setf test `(,(lambda (x) (+ x 1))))
>

Err.. in Scheme. In CL it is (obviously):

(setf test `(,#'(lambda (x) (+ x 1))))

Sunil Mishra

unread,
Mar 16, 1999, 3:00:00 AM3/16/99
to
joachim de beule <joa...@inwpent3.rug.ac.be> writes:

> Actually, it does not return an error, but this solution
> to my problem is a typing error by myself. I Actually
> wanted to write
>
> (setf test '(#'(lambda (x) (+ x 1))))
> (funcall (first test) 0)
>
> which produces the error.

'(#'(lambda(x) (+ x 1))) ==> (quote (function (lambda (x) (+ x 1))))

In other words, you have quoted a list containing a special form. You need
to evaluate that special form to get it to work right.

CL-USER 5 > (setf test '(#'(lambda (x) (+ x 1))))
((FUNCTION (LAMBDA (X) (+ X 1))))

CL-USER 12 > (funcall (eval (first test)) 0)
1

Sunil

Kent M Pitman

unread,
Mar 16, 1999, 3:00:00 AM3/16/99
to
joachim de beule <joa...@inwpent3.rug.ac.be> writes:

[I've pasted in the corrections here to get something clean to respond to.]


> > Can anyone tell my why
> > (funcall #'(lambda (x) (+ x 1)) 0)
> > evaluates to 1 as it should but

> > (setf test '(#'(lambda (x) (+ x 1))))
> > (funcall (first test) 0)

> > returns the error
> > Error: Illegal function object: #'(LAMBDA (X) (+ X 1))

#'(lambda (x) ...) is not notation for a function, it is notation
for an expression that yields a function. The actual function looks
in most implementations like #<FUNCTION ...> and cannot be typed in.

#'(lambda (x) ...) is *precisely* equivalent to
(function (lambda (x) ...)), so you have to evaluate it to make
a function of it. When you put quote around the containing expression,
you inhibited this evaluation. This fact is made slightly opaque by the
choice of your printer to print (function (lambda (x) (+ x 1)))
as its shorhand, so you are probably mistaking it for an object of its
own type. But if you have a function, you cannot (for example) take
car and cdr of it; but if you have a "function form", you can. So there
are material differences between a functionform, such as
(function (lambda (x) x)) and a function object such as results from
evaluating that. And function forms are simply not defined as functions.

Under CLTL1, (lambda (x) x) was FUNCTIONP (and would be coerced by
FUNCALL to an actual function) but this was fixed for ANSI CL. The
problem was that it defeats efficient deployment of applications. If
CONS is used anywhere in your program and if LAMBDA is used anywhere as
a symbol (or if INTERN is used and the argument might be "LAMBDA"),
that's powerful enough that you can cons up a funtion, so it means you
can never tree-shake out the interpreter because you can't prove it won't
be needed to do this coercion. Also, in practice, it leads to program
errors because people are bad about understanding that
(let ((x 0))
(declare (special x))
(funcall '(lambda () (let ((x 1)) (funcall '(lambda () x))))))
=> 0
Lambda expressions don't capture their environment, but functions do.
So making it harder to accidentally use a lambda expression as a function
makes it harder for people to accidentally fail to capture the environment.

Back to your example, you can use
(funcall (first '(#.#'(lambda (x) (+ x 1)))) 0)
if you aren't going to compile the code. (If you do compile the code,
you have a problem about externalizable objects; see the spec about that.
Compiling them is ok, but dumping it to a file is problematic.)
Doing:
(funcall (first `(,#'(lambda (x) (+ x 1)))) 0)
is safer because it emits code to accomplish the setup at runtime
instead of at read-time. Of course, in practice you wouldn't cons and
then immediately car into it, but I assume this is a small version of
a larger example using a fixed value from a variable somewhere.

You could also define your own #` which did the same as #.#' but that
wouldn't shield you from the underlying problem about externalization.

I hope this helps.

Howard R. Stearns

unread,
Mar 16, 1999, 3:00:00 AM3/16/99
to
Kent M Pitman wrote:
> ...

> Under CLTL1, (lambda (x) x) was FUNCTIONP (and would be coerced by
> FUNCALL to an actual function) but this was fixed for ANSI CL. The
> problem was that it defeats efficient deployment of applications. If
> CONS is used anywhere in your program and if LAMBDA is used anywhere as
> a symbol (or if INTERN is used and the argument might be "LAMBDA"),
> that's powerful enough that you can cons up a funtion, so it means you
> can never tree-shake out the interpreter because you can't prove it won't
> be needed to do this coercion.
> ...

Is this truly a (not necesarily THE,) principle reason for making
'(lambda ... ) not be functionp? I don't understand how this actually
helped tree shakers, given that INTERN remained, along with COERCE,
EVAL, COMPILE, MACROEXPAND, generic-functions and method-combination in
the absence of sealing, FORMAT, LOAD, COMPILE-FILE, readtables and the
#. reader, ...

Barry Margolin

unread,
Mar 16, 1999, 3:00:00 AM3/16/99
to
In article <36EE70F5...@iname.com>,

Fernando D. Mato Mira <mato...@iname.com> wrote:
>
>
>"Fernando D. Mato Mira" wrote:
>
>> That should be
>>
>> (setf test `(,(lambda (x) (+ x 1))))
>>
>
>Err.. in Scheme. In CL it is (obviously):
>
>(setf test `(,#'(lambda (x) (+ x 1))))

Actually, the first form should work in ANSI CL. It specifies a LAMBDA
macro that's equivalent to:

(defmacro lambda ((args) &body body)
`#'(lambda (,@args) ,@body))

so that it's not necessary to use #' with LAMBDA expressions.

--
Barry Margolin, bar...@bbnplanet.com
GTE Internetworking, Powered by BBN, Burlington, MA
*** DON'T SEND TECHNICAL QUESTIONS DIRECTLY TO ME, post them to newsgroups.
Please DON'T copy followups to me -- I'll assume it wasn't posted to the group.

Duane Rettig

unread,
Mar 16, 1999, 3:00:00 AM3/16/99
to
"Fernando D. Mato Mira" <mato...@iname.com> writes:

> "Fernando D. Mato Mira" wrote:
>
> > That should be
> >
> > (setf test `(,(lambda (x) (+ x 1))))
> >
>
> Err.. in Scheme. In CL it is (obviously):
>
> (setf test `(,#'(lambda (x) (+ x 1))))

Actually, no; Although your understanding was true as of CLtL2 time,
Ansi CL provides for a LAMBDA macro definition that expands to the
function in the intuitive way:

USER(3): (setf test `(,(lambda (x) (+ x 1))))
(#<Interpreted Function (unnamed) @ #x304d058a>)
USER(4): (funcall (first test) 0)
1
USER(5):

Of course, your second style also works, and was the only way to
do it in pre-Ansi CL.

--
Duane Rettig Franz Inc. http://www.franz.com/ (www)
1995 University Ave Suite 275 Berkeley, CA 94704
Phone: (510) 548-3600; FAX: (510) 548-8253 du...@Franz.COM (internet)

Vassil Nikolov

unread,
Mar 17, 1999, 3:00:00 AM3/17/99
to
In article <efybtht...@whizzy.cc.gatech.edu>,

Sunil Mishra <smi...@whizzy.cc.gatech.edu> wrote:
> joachim de beule <joa...@inwpent3.rug.ac.be> writes:
>

May I add, for completeness, that if you eval a (FUNCTION (LAMBDA ...))
form, you don't capture any lexical environments (because that's how
EVAL works in Common Lisp (as far as I know from SICP, Scheme is different
in this respect!)).

If I had to construct a function at runtime from a lambda expression,
personally I'd prefer using COERCE. (Just to avoid using EVAL, not
that COERCE is different with regard to lexical environments or perhaps
tree-shaking. Or, I could consider calling COMPILE (again, if you
have to dump an image, you should consider in your particular case
if you want it to carry the compiler).)

To sum up:
So, if you have the lambda expression appearing in the program as a
constant (and if you want to have a lexical closure, as one usually
does), in a for-evaluation position, you should either just put #'
in front, or nothing at all (in which case the LAMBDA macro does it
for you), but you should not put ' in front unless you use COERCE,
which you would not normally want for literal expressions. That is:

(funcall #'(lambda (x) (+ x 1)) 2) => 3 ;fine (1)
(funcall (lambda (x) (+ x 1)) 2) => 3 ;fine (2)
(funcall '(lambda (x) (+ x 1)) 2) ERROR! (3)
(funcall (coerce '(lambda (x) (+ x 1)) 'function) 2) => 3 (4)

Notes:

The argument to FUNCALL in (2) macroexpands to the argument to
FUNCALL in (1).

Some people go religious on whether (1) or (2) is better.

In CLtL (1st ed.) Common Lisp, (3) used to be legal (but didn't
produce a lexical closure either), and there may still be such
implementations in use.

Case (4) is legal but unnatural when the lambda expression is
explicit (and it wouldn't produce a lexical closure either).

(I am aware that I have restated in part what had been posted, but
thought getting all in one place and mentioning COERCE would pardon
me.)

Good luck,
Vassil.

Vassil Nikolov <vnik...@poboxes.com> www.poboxes.com/vnikolov
(You may want to cc your posting to me if I _have_ to see it.)
LEGEMANVALEMFVTVTVM (Ancient Roman programmers' adage.)

-----------== Posted via Deja News, The Discussion Network ==----------
http://www.dejanews.com/ Search, Read, Discuss, or Start Your Own

Erik Naggum

unread,
Mar 19, 1999, 3:00:00 AM3/19/99
to
* "Fernando D. Mato Mira" <mato...@iname.com>
| Now, if I understand what Barry and Kent said, this would _not_ be the
| same if the lambda contains free variables, so you can't just drop all
| uses of #' for anonymous functions.

you seem to say that there is a difference between (lambda ...) and
#'(lambda ...). how could that be?

#:Erik

Tim Bradshaw

unread,
Mar 19, 1999, 3:00:00 AM3/19/99
to
Erik Naggum <er...@naggum.no> writes:

> you seem to say that there is a difference between (lambda ...) and
> #'(lambda ...). how could that be?
>

There isn't now because LAMBDA is a macro which expands to #'(LAMBDA ...).
I think the original issue was that there was a difference between

(funcall #'(lambda ...))

and

(funcall '(lambda ...))

(which is no longer legal), because the second case would not see
lexical bindings. At least I think that's right.

--tim

Fernando D. Mato Mira

unread,
Mar 19, 1999, 3:00:00 AM3/19/99
to

Tim Bradshaw wrote:

Excellent!

Lieven Marchand

unread,
Mar 19, 1999, 3:00:00 AM3/19/99
to
Erik Naggum <er...@naggum.no> writes:

> * "Fernando D. Mato Mira" <mato...@iname.com>
> | Now, if I understand what Barry and Kent said, this would _not_ be the
> | same if the lambda contains free variables, so you can't just drop all
> | uses of #' for anonymous functions.
>

> you seem to say that there is a difference between (lambda ...) and
> #'(lambda ...). how could that be?
>

> #:Erik

According to the Hyperspec, par. 3.8.2 there shouldn't be any difference.

A note explicitly gives an implementation like

(defmacro lambda (&whole form &rest bvl-decls-and-body)
(declare (ignore bvl-decls-and-body))
`#',form)

--
Lieven Marchand

Steven M. Haflich

unread,
Mar 23, 1999, 3:00:00 AM3/23/99
to Kent M Pitman
Kent M Pitman wrote:

> As you probably recall, Steve, FUNCTION-TYPE went through numerous
> evolutions, only a tiny bit of it surving into the final writeup.
> I could publish a whole book out of the text of all the old versions.

I'm dropping the issue of why, since it's history and requires significant
effort to research. But I think, Kent, you misremember the result:

> Re-read FUNCTION-TYPE. The thing Beckerle really wanted and finally
> got (over my objection) was that COERCE did nothing `hard' ... What
> it ended up being able to be do can be expressed by #'IDENTITY and
> #'SYMBOL-FUNCTION.
>
> (COERCE x 'FUNCTION) ==
> (ETYPECASE X
> (SYMBOL (SYMBOL-VALUE X))
> (FUNCTION X))
>
> I don't really think anything more needs to be provided, even if we
> DEPRECATE coerce.

See the ANS dictionary entry for COERCE, particularly the second
paragraph reproduced below:

If the result-type is function, and object is any function name that
is fbound but that is globally defined neither as a macro name nor as
a special operator, then the result is the functional value of object.

If the result-type is function, and object is a lambda expression,
then the result is a closure of object in the null lexical
environment.

Kent M Pitman

unread,
Mar 24, 1999, 3:00:00 AM3/24/99
to

Oops.

0 new messages