From: Josef Tomas
Subject: Applying a lambda expression created in runtime
Date: 
Message-ID: <9a8eadbb-2f77-4aa9-acba-430e24f23af4@e6g2000prf.googlegroups.com>
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

From: ···············@gmail.com
Subject: Re: Applying a lambda expression created in runtime
Date: 
Message-ID: <a85a42ab-af4c-48a5-b32a-e9d742424f40@y5g2000hsf.googlegroups.com>
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.
From: Kaz Kylheku
Subject: Re: Applying a lambda expression created in runtime
Date: 
Message-ID: <85a3e9ba-d8c9-4f6f-b750-e37634e2c648@e4g2000hsg.googlegroups.com>
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
From: ······@gmail.com
Subject: Re: Applying a lambda expression created in runtime
Date: 
Message-ID: <bd6ad2ed-9b26-47ba-9ce3-3df68bfd0f75@q21g2000hsa.googlegroups.com>
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
From: ······@gmail.com
Subject: Re: Applying a lambda expression created in runtime
Date: 
Message-ID: <d4742e46-ef4d-4dda-9fe2-070fd8c6794b@f10g2000hsf.googlegroups.com>
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
From: ······@gmail.com
Subject: Re: Applying a lambda expression created in runtime
Date: 
Message-ID: <1ef66a5a-0727-4ccc-bb24-d759f58c8f71@v67g2000hse.googlegroups.com>
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.
From: Zach Beane
Subject: Re: Applying a lambda expression created in runtime
Date: 
Message-ID: <m363x876jg.fsf@unnamed.xach.com>
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
From: Pascal Costanza
Subject: Re: Applying a lambda expression created in runtime
Date: 
Message-ID: <60hi6bF1qlbmmU1@mid.individual.net>
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/