I tried to apply a lambda expression that I composed at runtime as
shown in the following example, but it did not work:
> (defun foo (var-list body value-list)
(apply (list 'lambda var-list body) value-list))
FOO
> (foo '(X Y) '(+ X Y) '(1 2))
Error: Argument to apply/funcall is not a function: (LAMBDA (X Y) (+ X
Y)).
It works using eval (after mapcar-quoting value-list), but I wonder
whether apply or funcall can be persuaded to do the job ...
Thanks for advice, Josef
On Feb 1, 2:16 pm, Josef Tomas <·····@fel.cvut.cz> wrote:
> I tried to apply a lambda expression that I composed at runtime as
> shown in the following example, but it did not work:
>
> > (defun foo (var-list body value-list)
>
> (apply (list 'lambda var-list body) value-list))
> FOO
>
> > (foo '(X Y) '(+ X Y) '(1 2))
>
> Error: Argument to apply/funcall is not a function: (LAMBDA (X Y) (+ X
> Y)).
>
> It works using eval (after mapcar-quoting value-list), but I wonder
> whether apply or funcall can be persuaded to do the job ...
>
> Thanks for advice, Josef
There are a couple ways to do this.
(coerce (list 'lambda ...) 'function)
(compile nil (list 'lambda ...))
I believe the idea is that COERCE might leave you with an interpreted
function, while COMPILE does the COERCE first, then does enough
compiling to satisfy COMPILED-FUNCTION-P.
On Feb 1, 11:16 am, Josef Tomas <·····@fel.cvut.cz> wrote:
> I tried to apply a lambda expression that I composed at runtime as
> shown in the following example, but it did not work:
>
> > (defun foo (var-list body value-list)
>
> (apply (list 'lambda var-list body) value-list))
Apply takes only two kinds of objects as its first argument, a
function or a symbol. If a symbol is given, it's internally resolved
to a function as if by SYMBOL-FUNCTION.
Here you are passing a list, which represents the source code of a
function. APPLY isn't a an evaluator or compiler; it doesn't deal with
source code.
You have to deal with the source code using EVAL or COMPILE, either of
which will reduce it to a function:
(eval (list 'lambda var-list body)) -> #<function ...>
(compile nil (list 'lambda var-list body)) -> #<function ...>
These resulting functions can then be used in FUNCALL, APPLY, MAPCAR,
etc.
> FOO
>
> > (foo '(X Y) '(+ X Y) '(1 2))
>
> Error: Argument to apply/funcall is not a function: (LAMBDA (X Y) (+ X
> Y)).
>
> It works using eval (after mapcar-quoting value-list), but I wonder
> whether apply or funcall can be persuaded to do the job ...
A portable Lisp program can't change the behavior of FUNCALL and
APPLY. In your own package, though you can have your own FUNCALL and
APPLY symbols which name your own functions:
(defpackage "MY-PACKAGE"
(:use "CL")
(:shadow "APPLY" "FUNCALL"))
(in-package "MY-PACKAGE")
(defun funcall (obj &rest args)
(if (consp obj)
(cl:apply (eval obj) args)
(cl:apply obj args)))
(defun apply (obj &rest spreadable-args)
(if (consp obj)
(cl:apply #'cl:apply (eval obj) spreadable-args)
(cl:apply #'cl:apply obj spreadable-args))
Of course, you have to wrap every single CL function in which you want
this flexibility. For instance even if MAPCAR internally works by
using APPLY, it won't be calling /your/ APPLY. Your apply is MY-
PACKAGE::APPLY, not CL:APPLY.
Hmm, I've never applied APPLY to APPLY before, but that's the thing to
do if you are wrapping APPLY with a function which is to provide the
same interface.
The funcall wrapper takes advantage of (apply #'funcall f ...) being
equivalent to (apply f ...).
From: Maciej Katafiasz
Subject: Re: Applying a lambda expression created in runtime
Date:
Message-ID: <fnvs08$bel$1@news.net.uni-c.dk>
Den Fri, 01 Feb 2008 11:16:10 -0800 skrev Josef Tomas:
> I tried to apply a lambda expression that I composed at runtime as shown
> in the following example, but it did not work:
>
>> (defun foo (var-list body value-list)
> (apply (list 'lambda var-list body) value-list))
> FOO
>> (foo '(X Y) '(+ X Y) '(1 2))
>
> Error: Argument to apply/funcall is not a function: (LAMBDA (X Y) (+ X
> Y)).
>
> It works using eval (after mapcar-quoting value-list), but I wonder
> whether apply or funcall can be persuaded to do the job ...
Not really. LAMBDA is a special form, not a function, so you can't really
APPLY it. If you really need truly runtime code generation, I'm afraid
there's no escaping EVAL. But it might be that your particular problem
doesn't need it, what is it that you're trying to do?
Cheers,
Maciej
On Feb 1, 8:30 pm, Maciej Katafiasz <········@gmail.com> wrote:
> Not really. LAMBDA is a special form, not a function, so you can't really
> APPLY it. If you really need truly runtime code generation, I'm afraid
> there's no escaping EVAL. But it might be that your particular problem
> doesn't need it, what is it that you're trying to do?
>
> Cheers,
> Maciej
Are you sure that you are talking about common lisp ?
(first try in repl some of the stuff you are saying)
From: Maciej Katafiasz
Subject: Re: Applying a lambda expression created in runtime
Date:
Message-ID: <fnvtpt$bel$4@news.net.uni-c.dk>
Den Fri, 01 Feb 2008 11:54:12 -0800 skrev ······@gmail.com:
>> Not really. LAMBDA is a special form, not a function, so you can't
>> really APPLY it. If you really need truly runtime code generation, I'm
>> afraid there's no escaping EVAL. But it might be that your particular
>> problem doesn't need it, what is it that you're trying to do?
>>
> Are you sure that you are talking about common lisp ?
Yes?
> (first try in repl some of the stuff you are saying)
You mean what exactly? The necessity of EVAL or the fact that LAMBDA is
not a function?
Maciej
On Feb 1, 9:01 pm, Maciej Katafiasz <········@gmail.com> wrote:
> Den Fri, 01 Feb 2008 11:54:12 -0800 skrev ······@gmail.com:
>
> >> Not really. LAMBDA is a special form, not a function, so you can't
> >> really APPLY it. If you really need truly runtime code generation, I'm
> >> afraid there's no escaping EVAL. But it might be that your particular
> >> problem doesn't need it, what is it that you're trying to do?
>
> > Are you sure that you are talking about common lisp ?
>
> Yes?
>
> > (first try in repl some of the stuff you are saying)
>
> You mean what exactly? The necessity of EVAL or the fact that LAMBDA is
> not a function?
>
> Maciej
both
············@ answered first one
... and Josef Tomas is trying to create anonymous function with lambda
in his code, so your comment about lambda/special form/apply is
inessential.
From: Maciej Katafiasz
Subject: Re: Applying a lambda expression created in runtime
Date:
Message-ID: <fo036f$bel$7@news.net.uni-c.dk>
Den Fri, 01 Feb 2008 12:21:00 -0800 skrev ······@gmail.com:
>> > Are you sure that you are talking about common lisp ?
>>
>> Yes?
>>
>> > (first try in repl some of the stuff you are saying)
>>
>> You mean what exactly? The necessity of EVAL or the fact that LAMBDA is
>> not a function?
>>
> both
> ············@ answered first one
> ... and Josef Tomas is trying to create anonymous function with lambda
> in his code, so your comment about lambda/special form/apply is
> inessential.
············@ suggested COERCE (which is functionally equivalent to EVAL
in this case, and in fact, will do (eval `#',object) in SBCL, I expect a
very similar codepath in other implementations) or COMPILE (which will do
the same thing as EVAL, except that it might do more to satisfy COMPILED-
FUNCTION-P)
... and Josef Tomas is trying to create such a function *from code passed
at runtime*, so your remarks are clueless and inessential.
LAMBDA is not a function. LAMBDA lets you *create* functions, but itself
isn't one. The same way LIST will let you create lists, but itself isn't
a list.
Maciej
On Feb 1, 10:33 pm, Maciej Katafiasz <········@gmail.com> wrote:
> Den Fri, 01 Feb 2008 12:21:00 -0800 skrev ······@gmail.com:
>
> >> > Are you sure that you are talking about common lisp ?
>
> >> Yes?
>
> >> > (first try in repl some of the stuff you are saying)
>
> >> You mean what exactly? The necessity of EVAL or the fact that LAMBDA is
> >> not a function?
>
> > both
> > ············@ answered first one
> > ... and Josef Tomas is trying to create anonymous function with lambda
> > in his code, so your comment about lambda/special form/apply is
> > inessential.
>
> ············@ suggested COERCE (which is functionally equivalent to EVAL
> in this case, and in fact, will do (eval `#',object) in SBCL, I expect a
> very similar codepath in other implementations) or COMPILE (which will do
> the same thing as EVAL, except that it might do more to satisfy COMPILED-
> FUNCTION-P)
> ... and Josef Tomas is trying to create such a function *from code passed
> at runtime*, so your remarks are clueless and inessential.
>
> LAMBDA is not a function. LAMBDA lets you *create* functions, but itself
> isn't one. The same way LIST will let you create lists, but itself isn't
> a list.
>
> Maciej
Why do you insist that lambda is not function, i know that, but that
is not point in this discussion.
Maciej Katafiasz <········@gmail.com> writes:
> If you really need truly runtime code generation, I'm afraid there's
> no escaping EVAL.
Not true; take a look at how CL-PPCRE converts regular expression
syntax to efficient closures, at runtime, without calling EVAL or
COMPILE.
Zach
From: Maciej Katafiasz
Subject: Re: Applying a lambda expression created in runtime
Date:
Message-ID: <fo02cg$bel$6@news.net.uni-c.dk>
Den Fri, 01 Feb 2008 15:42:11 -0500 skrev Zach Beane:
>> If you really need truly runtime code generation, I'm afraid there's no
>> escaping EVAL.
>
> Not true; take a look at how CL-PPCRE converts regular expression syntax
> to efficient closures, at runtime, without calling EVAL or COMPILE.
http://xach.livejournal.com/131456.html? Yes, I'm fully aware of that,
I've hinted at that technique recently in the unification terms
collection thread. But CL-PPCRE can do that because it has finite syntax.
Notice that I specifically used the qualifier "truly runtime". If you
need to be able to create an arbitrary function at runtime, you have to
use EVAL or COMPILE at some point.
Cheers,
Maciej
Josef Tomas wrote:
> I tried to apply a lambda expression that I composed at runtime as
> shown in the following example, but it did not work:
>
>> (defun foo (var-list body value-list)
> (apply (list 'lambda var-list body) value-list))
> FOO
>> (foo '(X Y) '(+ X Y) '(1 2))
>
> Error: Argument to apply/funcall is not a function: (LAMBDA (X Y) (+ X
> Y)).
>
> It works using eval (after mapcar-quoting value-list), but I wonder
> whether apply or funcall can be persuaded to do the job ...
>
> Thanks for advice, Josef
This seems very low level. What do you actually need this for? There
might be a better solution...
Pascal
--
1st European Lisp Symposium (ELS'08)
http://prog.vub.ac.be/~pcostanza/els08/
My website: http://p-cos.net
Common Lisp Document Repository: http://cdr.eurolisp.org
Closer to MOP & ContextL: http://common-lisp.net/project/closer/