From: David E. Young
Subject: Function composition at run time
Date: 
Message-ID: <39EDFA1B.145997A4@nc.rr.com>
Greetings. Ok, I really should know the answer to this question but the
solution is eluding me.

I've an application that needs to create a function object from a list
of forms; for example, something like:

  (compose '((let ((foo "schtum")) (print foo))))

should yield the function object #'(lambda () (let ((foo "schtum"))
(print foo))).

My first attempt was the following macro:

(defmacro compose-function (expr)
  (labels ((compose-body (forms &optional (body nil))
             (if (null forms)
                 body
               (compose-body (rest forms)
                             (nconc body
                                    `(,(first forms)))))))
    `#',(compose-body expr (list 'lambda ()))))

This actually works if invoked like:

  (compose-function ((let ((foo "schtum")) (print foo))))

However, it breaks down of course with something like:

  (let ((forms '((let ((foo "schtum")) (print foo)))))
     (compose-function forms))

Clearly, the above doesn't work because the macro doesn't evaluate it's
argument before calling COMPOSE-BODY. And, this is where I'm stuck. I
began by doing this:

(defmacro compose-function (expr)
   (let ((forms (gensym)))
      `(let ((,forms ,expr))

But now what? I think I'm close; thanks for the assistance.

Regards,

--
-----------------------------------------------------------------
David E. Young
Fujitsu Network Communications  "The fact that ... we still
(···········@fnc.fujitsu.com)    live well cannot ease the pain of
                                 feeling that we no longer live nobly."
                                  -- John Updike
"Programming should be fun,
 programs should be beautiful"
  -- P. Graham

From: Rainer Joswig
Subject: Re: Function composition at run time
Date: 
Message-ID: <joswig-AC5DEA.22314318102000@news.is-europe.net>
In article <·················@nc.rr.com>, ·······@nc.rr.com wrote:

> I've an application that needs to create a function object from a list
> of forms; for example, something like:
> 
>   (compose '((let ((foo "schtum")) (print foo))))

(eval '(lambda () (let ((foo "schtum")) (print foo))))

If you want to do it at runtime, you have to use COMPILE
or EVAL.


> (defmacro compose-function (expr)
>    (let ((forms (gensym)))
>       `(let ((,forms ,expr))

You seem to be puzzled by the difference between runtime and
compile time. Macro Expansion is done before runtime.

-- 
Rainer Joswig, Hamburg, Germany
Email: ·············@corporate-world.lisp.de
Web: http://corporate-world.lisp.de/
From: David E. Young
Subject: Re: Function composition at run time
Date: 
Message-ID: <39EE12BC.A053F10@nc.rr.com>
Rainer Joswig wrote:

> In article <·················@nc.rr.com>, ·······@nc.rr.com wrote:
>
> > I've an application that needs to create a function object from a list
> > of forms; for example, something like:
> >
> >   (compose '((let ((foo "schtum")) (print foo))))
>
> (eval '(lambda () (let ((foo "schtum")) (print foo))))
>
> If you want to do it at runtime, you have to use COMPILE
> or EVAL.
>

>
> You seem to be puzzled by the difference between runtime and
> compile time. Macro Expansion is done before runtime.

No; I know when macro expansion is performed, and I have some knowledge of
the differences between runtime and compile time (although I'm sure there
are gaps in that knowledge).

Let me be more clear. I've an embedded language that allows access to Lisp.
I must take these forms, do some variable binding work and then allow them
to be evaluated. These forms are part of a language "statement" that I
extract through parsing. I intended to build a function object by splicing
these forms in via macro expansion, hence my question.

Does that help, or am I still being vague?

Regards,

--
-----------------------------------------------------------------
David E. Young
Fujitsu Network Communications  "The fact that ... we still
(···········@fnc.fujitsu.com)           live well cannot ease the pain of

feeling that we no longer live nobly."
                                                                       --
John Updike
"Programming should be fun,
 programs should be beautiful"
  -- P. Graham
From: Rainer Joswig
Subject: Re: Function composition at run time
Date: 
Message-ID: <joswig-9397E6.23384818102000@news.is-europe.net>
In article <················@nc.rr.com>, ·······@nc.rr.com wrote:

> No; I know when macro expansion is performed, and I have some knowledge of
> the differences between runtime and compile time (although I'm sure there
> are gaps in that knowledge).
> 
> Let me be more clear. I've an embedded language that allows access to Lisp.
> I must take these forms, do some variable binding work and then allow them
> to be evaluated. These forms are part of a language "statement" that I
> extract through parsing. I intended to build a function object by splicing
> these forms in via macro expansion, hence my question.

When do you get your code? At runtime of your Lisp program?

(defmacro do-something-with-form (form)
   ...)

(let ((form (get-some-form)))
   (do-something-with-form form))

In above version the macro expansion happens
before runtime. So the macro sees the source
("form") and not the runtime value of form.
It is still necessary to use EVAL or COMPILE
at runtime (inside of do-something-with-form)
to get back a *function-object* .

So, let's build an example:

Say, the running Lisp program has two variables
that you want to bind:

(defparameter *user* nil)  ; the script should see USER
(defparameter *server* nil)  ; the script should see SERVER

One Function gives you a Lisp form. We will get it at
runtime from the user - somehow:

(defun get-lisp-form ()
  (read))

Now you want to generate a Lisp function:

(defun generate-lisp-function (form)
  (eval `(lambda ()
           (let ((user ,*user*)
                 (server ,*server*))
             (declare (ignorable user server))
             ,form))))

Now do:

(let ((new-function (let ((*user* "Rainer")
                          (*server* "Lispm"))
                      (generate-lisp-function (get-lisp-form)))))
  (funcall new-function))

And enter following code:  (list 'foo (concatenate 'string user ·@" server) 'bar)

-- 
Rainer Joswig, Hamburg, Germany
Email: ·············@corporate-world.lisp.de
Web: http://corporate-world.lisp.de/
From: David E. Young
Subject: Re: Function composition at run time
Date: 
Message-ID: <39EE33D6.A7575B2C@nc.rr.com>
Rainer Joswig wrote:

>
> When do you get your code? At runtime of your Lisp program?
>

Forgive me Rainer; I see from my original posting where the confusion arises. The
code in question actually gets evaluated at load time. Here's an example that mimics
our embedded language:

(defmacro language-statement (name &body body)
  `(parse-statement body))

and in another file perhaps:

(language-statement 'foo
   (when
      (condition-1)
      (condition-2)
     then
       (let ((foo "schtum"))
            (print foo))))

Somewhere during the parsing of BODY the Lisp forms I mentioned (those appearing
after THEN) are extracted and stored away for later (i.e. actual runtime)
evaluation. After looking at some exampels in Graham's "On Lisp" I was hoping I
could splice these forms into a function object and just FUNCALL the object whenever
necessary. Perhaps I can't? Should I just store the forms and call EVAL at the
appropriate time instead?

Regards,

--
-----------------------------------------------------------------
David E. Young
Fujitsu Network Communications  "The fact that ... we still
(···········@fnc.fujitsu.com)           live well cannot ease the pain of
                                                                     feeling that we
no longer live nobly."
                                                                      -- John Updike

"Programming should be fun,
 programs should be beautiful"
  -- P. Graham
From: Erik Naggum
Subject: Re: Function composition at run time
Date: 
Message-ID: <3180969984634156@naggum.net>
* "David E. Young" <·······@nc.rr.com>
| I was hoping I could splice these forms into a function object and
| just FUNCALL the object whenever necessary.

  Back in the old days, funcall (and friends) treated an argument that
  was a list whose car was the symbol lambda as a function.  Some
  Common Lisp implementations still do that out of courtesy to the old
  ways, but ANSI Common Lisp specifies that they should be coerced
  into functions as if by evaluating (eval `(function ,<lambda-expr>))
  before being funcallable.

| Perhaps I can't? Should I just store the forms and call EVAL at the
| appropriate time instead?

  Suppose you have a list of forms to evaluate in a variable <list>.
  (eval `(progn ,<list>)) will evaluate them in order.  If you want a
  function object, you need (eval `(function (lambda () ,<list>))),
  and then you need to funcall the result.  Unless you want to compile
  the function, as in (compile nil `(lambda () ,<list>)), of course.
  In most cases, the progn solution should be quite adequate.

#:Erik
-- 
  I agree with everything you say, but I would
  attack to death your right to say it.
				-- Tom Stoppard
From: Aaron Crane
Subject: Re: Function composition at run time
Date: 
Message-ID: <djy9zla828.fsf@planet.dcs.ed.ac.uk>
In article <·················@nc.rr.com>,
"David E. Young" <·······@nc.rr.com> writes:
> I was hoping I could splice these forms into a function object and just
> FUNCALL the object whenever necessary. Perhaps I can't? Should I just
> store the forms and call EVAL at the appropriate time instead?

I suspect you're really looking for COERCE and/or COMPILE.

  (let* ((f (coerce '(lambda (x) (+ x 42)) 'function))
         (c1 (compile nil f))
         (c2 (compile nil '(lambda (x) (+ x 42)))))
    (values (functionp f)
            (compiled-function-p c1)
            (compiled-function-p c2)))
 => T T T

-- 
Aaron Crane
From: David E. Young
Subject: Re: Function composition at run time
Date: 
Message-ID: <39EE4F78.E103FD5B@nc.rr.com>
Rainer Joswig wrote:

>
> So, let's build an example...

Thanks very much, Rainer; it's clear to me now. Sorry, I still suffer from a lack of
clarity as to when it's appropriate to use EVAL. Much obliged for setting me
straight.

Regards,

--
-----------------------------------------------------------------
David E. Young
Fujitsu Network Communications  "The fact that ... we still
(···········@fnc.fujitsu.com)    live well cannot ease the pain of
                                 feeling that we no longer live nobly."
                                  -- John Updike
"Programming should be fun,
 programs should be beautiful"
  -- P. Graham
From: Rainer Joswig
Subject: Re: Function composition at run time
Date: 
Message-ID: <joswig-9CDC70.04063219102000@news.is-europe.net>
In article <·················@nc.rr.com>, ·······@nc.rr.com wrote:

> Rainer Joswig wrote:
> 
> >
> > So, let's build an example...
> 
> Thanks very much, Rainer; it's clear to me now. Sorry, I still suffer from a lack of
> clarity as to when it's appropriate to use EVAL. Much obliged for setting me
> straight.

You can use EVAL when you want to use new Lisp source code at runtime
(see also: READ, LOAD, COMPILE-FILE, COMPILE).

To puzzle a bit - look at this:

(defmacro generate-function-form (form)
  `(lambda ()
     (let ((user ,*user*)
           (server ,*server*))
       (declare (ignorable user server))
       ,form)))

(defun generate-lisp-function (form)
  (eval `(generate-function-form ,form)))

Or:

(defun generate-function-form (form)
  `(lambda ()
     (let ((user ,*user*)
           (server ,*server*))
       (declare (ignorable user server))
       ,form)))

(defun generate-lisp-function (form)
  (eval (generate-function-form form)))


You can get around calling EVAL by writing your own interpreter for
your scripting language and call that instead (see for example
the Scheme chapters in PAIP).

-- 
Rainer Joswig, Hamburg, Germany
Email: ·············@corporate-world.lisp.de
Web: http://corporate-world.lisp.de/
From: David E. Young
Subject: Re: Function composition at run time
Date: 
Message-ID: <39EEFF00.A47AAE95@nc.rr.com>
Rainer Joswig wrote:

> To puzzle a bit - look at this:
>
> (defmacro generate-function-form (form)
>   `(lambda ()
>      (let ((user ,*user*)
>            (server ,*server*))
>        (declare (ignorable user server))
>        ,form)))
>
> (defun generate-lisp-function (form)
>   (eval `(generate-function-form ,form)))
>
> Or:
>
> (defun generate-function-form (form)
>   `(lambda ()
>      (let ((user ,*user*)
>            (server ,*server*))
>        (declare (ignorable user server))
>        ,form)))
>
> (defun generate-lisp-function (form)
>   (eval (generate-function-form form)))
>

So; as I read this the first case hands EVAL a DEFMACRO form; the second case gives EVAL
a LAMBDA expression. Is there a preference? Intuitively, I would think the latter.

Regards,

--
-----------------------------------------------------------------
David E. Young
Fujitsu Network Communications  "The fact that ... we still
(···········@fnc.fujitsu.com)    live well cannot ease the pain of
                                 feeling that we no longer live nobly."
                                  -- John Updike
"Programming should be fun,
 programs should be beautiful"
  -- P. Graham
From: Jochen Schmidt
Subject: Re: Function composition at run time
Date: 
Message-ID: <8sn1ug$l4a0c$1@ID-22205.news.cis.dfn.de>
No I think in the first version, the "generate-function-form" is generated
at compile time (one time) and the eval gets only the result. (right?)

The second version generates the list-structure each time you call 
generate-lisp-function.

The first version seems like somewhat like a inline version to the second.

Am I right???

Regards,
Jochen Schmidt

David E. Young wrote:

> Rainer Joswig wrote:
> 
> > To puzzle a bit - look at this:
> >
> > (defmacro generate-function-form (form)
> >   `(lambda ()
> >      (let ((user ,*user*)
> >            (server ,*server*))
> >        (declare (ignorable user server))
> >        ,form)))
> >
> > (defun generate-lisp-function (form)
> >   (eval `(generate-function-form ,form)))
> >
> > Or:
> >
> > (defun generate-function-form (form)
> >   `(lambda ()
> >      (let ((user ,*user*)
> >            (server ,*server*))
> >        (declare (ignorable user server))
> >        ,form)))
> >
> > (defun generate-lisp-function (form)
> >   (eval (generate-function-form form)))
> >
> 
> So; as I read this the first case hands EVAL a DEFMACRO form; the second
> case gives EVAL a LAMBDA expression. Is there a preference? Intuitively, I
> would think the latter.
> 
> Regards,
> 
> --
> -----------------------------------------------------------------
> David E. Young
> Fujitsu Network Communications  "The fact that ... we still
> (···········@fnc.fujitsu.com)    live well cannot ease the pain of
>                                  feeling that we no longer live nobly."
>                                   -- John Updike
> "Programming should be fun,
>  programs should be beautiful"
>   -- P. Graham
> 
> 
> 

-- 
From: David E. Young
Subject: Re: Function composition at run time
Date: 
Message-ID: <39EF3417.98AA1061@nc.rr.com>
Jochen Schmidt wrote:

> No I think in the first version, the "generate-function-form" is generated
> at compile time (one time) and the eval gets only the result. (right?)
>
> The second version generates the list-structure each time you call
> generate-lisp-function.
>
> The first version seems like somewhat like a inline version to the second.
>
> Am I right???

Here's what I get when I macroexpand each version in ACL 5.0 (Linux):

Version 1: (EVAL (EXCL::BQ-LIST 'GENERATE-FUNCTION-FORM FORM))

 Version 2: (EVAL (LAMBDA NIL (LET ((USER NIL) (SERVER NIL)) (DECLARE
(IGNORABLE USER SERVER)) FORM)))

--
-----------------------------------------------------------------
David E. Young
Fujitsu Network Communications  "The fact that ... we still
(···········@fnc.fujitsu.com)    live well cannot ease the pain of
                                 feeling that we no longer live nobly."
                                  -- John Updike
"Programming should be fun,
 programs should be beautiful"
  -- P. Graham
From: David E. Young
Subject: Re: Function composition at run time
Date: 
Message-ID: <39EF4C26.8FA1292F@nc.rr.com>
Thanks to everyone for responding. I've both a decent solution and a
better understanding of macro expansion.

Regards,

--
-----------------------------------------------------------------
David E. Young
Fujitsu Network Communications  "The fact that ... we still
(···········@fnc.fujitsu.com)    live well cannot ease the pain of
                                 feeling that we no longer live nobly."
                                  -- John Updike
"Programming should be fun,
 programs should be beautiful"
  -- P. Graham