A question which should be easy to answer, but has me stumped:
Given a list which looks like Lisp code, how does one create a
function with a modified version of that code as its body?
Currently, I use:
(defmacro make-modified-function (body arg-for-modifier)
`#'(lambda (arg)
,(modify-body-somehow body arg-for-modifier)))
(For my application, I don't care that 'arg' isn't a gensym.) If I
say "(make-modified-function (equal 1 2) (stuff1 stuff2))" I get back
the new function I intend. But this works very differently (in CMU
Common Lisp 17f under HP-UX) if I say:
(let ((body '(equal 1 2))
(other '(stuff1 stuff2)))
(make-modified-function body other))
It seems as if an implicit quote has suddenly been wrapped around each
of "body" and "other"! Why did this happen? How can I get the effect
I intend?
Any insights or workarounds would be appreciated!
Thanks,
Wheeler
--
Wheeler Ruml, Aiken 220, ····@das.harvard.edu, (617) 496-1066 (fax)
http://www.das.harvard.edu/users/students/Wheeler_Ruml/Wheeler_Ruml.html
From: Barry Margolin
Subject: Re: Dynamically building functions (and macroexpansion)
Date:
Message-ID: <3o3ulh$4uv@tools.near.net>
In article <·················@bowmore.harvard.edu> ····@bowmore.harvard.edu (Wheeler Ruml) writes:
>(defmacro make-modified-function (body arg-for-modifier)
> `#'(lambda (arg)
> ,(modify-body-somehow body arg-for-modifier)))
...
>(let ((body '(equal 1 2))
> (other '(stuff1 stuff2)))
> (make-modified-function body other))
>
>It seems as if an implicit quote has suddenly been wrapped around each
>of "body" and "other"! Why did this happen? How can I get the effect
>I intend?
Macro arguments aren't evaluated. So when you do (make-modified-function
body other), the MAKE-MODIFIED-FUNCTION macro receives the arguments BODY
and OTHER, not the values of those variables. Remember that macros are
normally executed at compile time, but variable values aren't available
until runtime.
Look back at the code you said did what you expected:
(make-modified-function (equal 1 2) (stuff1 stuff2))
In this case, it works precisely *because* the macro arguments aren't
evaluated. If they were, MAKE-MODIFIED-FUNCTION would receive the
arguments NIL and whatever (stuff1 stuff2) returns.
--
Barry Margolin
BBN Planet Corporation, Cambridge, MA
······@bbnplanet.com
In article <··········@tools.near.net>, Barry Margolin writes:
>In article <·················@bowmore.harvard.edu>, Wheeler Ruml writes:
>
>>(defmacro make-modified-function (body arg-for-modifier)
>> `#'(lambda (arg)
>> ,(modify-body-somehow body arg-for-modifier)))
>...
>>(let ((body '(equal 1 2))
>> (other '(stuff1 stuff2)))
>> (make-modified-function body other))
>
>Macro arguments aren't evaluated. So when you do (make-modified-function
>body other), the MAKE-MODIFIED-FUNCTION macro receives the arguments BODY
>and OTHER, not the values of those variables. Remember that macros are
>normally executed at compile time, but variable values aren't available
>until runtime.
Ah - of course! So my only option is to cons up a lambda expression
and "eval" it?
Thanks for your help,
Wheeler
--
Wheeler Ruml, Aiken 220, ····@das.harvard.edu, (617) 496-1066 (fax)
http://www.das.harvard.edu/users/students/Wheeler_Ruml/Wheeler_Ruml.html
From: Kevin Gallagher
Subject: Re: Dynamically building functions (and macroexpansion)
Date:
Message-ID: <3o5v8s$s8p@kernighan.cs.umass.edu>
Wheeler Ruml <····@bowmore.harvard.edu> writes:
>Barry Margolin writes:
>
>>Wheeler Ruml writes:
>>
>>>(defmacro make-modified-function (body arg-for-modifier)
>>> `#'(lambda (arg)
>>> ,(modify-body-somehow body arg-for-modifier)))
>>...
>>>(let ((body '(equal 1 2))
>>> (other '(stuff1 stuff2)))
>>> (make-modified-function body other))
>>
>>Macro arguments aren't evaluated. So when you do (make-modified-function
>>body other), the MAKE-MODIFIED-FUNCTION macro receives the arguments BODY
>>and OTHER, not the values of those variables. Remember that macros are
>>normally executed at compile time, but variable values aren't available
>>until runtime.
>
>Ah - of course! So my only option is to cons up a lambda expression
>and "eval" it?
Whenever you are tempted to use eval, first think long and hard about
whether you really need eval. In most cases there is a better way.
Maybe it would help if you could give us a bit more information about
what you're trying to do.
Kevin Gallagher
From: Barry Margolin
Subject: Re: Dynamically building functions (and macroexpansion)
Date:
Message-ID: <3o6adr$71u@tools.near.net>
In article <·················@bowmore.harvard.edu> ····@bowmore.harvard.edu (Wheeler Ruml) writes:
>Ah - of course! So my only option is to cons up a lambda expression
>and "eval" it?
Or use lexical closures.
--
Barry Margolin
BBN Planet Corporation, Cambridge, MA
······@bbnplanet.com
Thanks everyone, for responding to my posts. I appreciate your help.
To summarize, I'm trying to generate a new function whose body
consists of code that I compute at run-time (supposedly a classic Lisp
maneuver, pointers to a good text gladly accepted). My naive attempt
used macros to construct a lambda expression (clearly wrong since the
code isn't available until run-time). Now my code has this style:
(defun make-modified-function (body-prototype arg-for-maker)
(eval `(function (lambda (arg)
,(make-body-code body-prototype
arg-for-maker)))))
Supposedly, the use of eval is justified, since the code isn't
available until run-time. Barry Margolin had this suggestion:
>Ah - of course! So my only option is to cons up a lambda expression
>>and "eval" it?
>
>Or use lexical closures.
I'm not sure what you're getting at here. Is there a way to avoid
eval? I don't think I can use "function" directly, since it's a
special form and the body code needs to be computed on the spot.
Thanks,
Wheeler
--
Wheeler Ruml, Aiken 220, ····@das.harvard.edu, (617) 496-1066 (fax)
http://www.das.harvard.edu/users/students/Wheeler_Ruml/Wheeler_Ruml.html
From: Barry Margolin
Subject: Re: Dynamically building functions (and macroexpansion)
Date:
Message-ID: <3o9n9i$95s@tools.near.net>
In article <·················@bowmore.harvard.edu> ····@bowmore.harvard.edu (Wheeler Ruml) writes:
>>Or use lexical closures.
>
>I'm not sure what you're getting at here. Is there a way to avoid
>eval? I don't think I can use "function" directly, since it's a
>special form and the body code needs to be computed on the spot.
Instead of having the caller pass a piece of lisp code, have it pass a
lexical closure. E.g. instead of
(make-modified-function ... (eq a b))
use
(make-modified-function ... #'(lambda (a b) (eq a b)))
(defun make-modified-function (proto-function maker-function)
#'(lambda (arg)
(execute-body-code proto-function maker-function)))
Since I don't know what your original MAKE-BODY-CODE does, I can't show
what EXECUTE-BODY-CODE should look like.
--
Barry Margolin
BBN Planet Corporation, Cambridge, MA
······@bbnplanet.com
In article <·················@bowmore.harvard.edu> ····@bowmore.harvard.edu (Wheeler Ruml) writes:
To summarize, I'm trying to generate a new function whose body
consists of code that I compute at run-time (supposedly a classic Lisp
maneuver, pointers to a good text gladly accepted).
Anyone doing things like this will pobably benefit from reading the book
On Lisp by Paul Graham (Prentice Hall publ.) It has very extensive and
clear coverage of methods for constructing functions at runtime.
From: Luigi Semenzato
Subject: Re: Dynamically building functions (and macroexpansion)
Date:
Message-ID: <3o5rrp$ems@fido.asd.sgi.com>
In article <·················@bowmore.harvard.edu>, ····@bowmore.harvard.edu
(Wheeler Ruml) writes:
|> Given a list which looks like Lisp code, how does one create a
|> function with a modified version of that code as its body?
|>
|> Currently, I use:
|>
|> (defmacro make-modified-function (body arg-for-modifier)
|> `#'(lambda (arg)
|> ,(modify-body-somehow body arg-for-modifier)))
|>
|> (For my application, I don't care that 'arg' isn't a gensym.) If I
|> say "(make-modified-function (equal 1 2) (stuff1 stuff2))" I get back
|> the new function I intend. But this works very differently (in CMU
|> Common Lisp 17f under HP-UX) if I say:
|>
|> (let ((body '(equal 1 2))
|> (other '(stuff1 stuff2)))
|> (make-modified-function body other))
|>
|> It seems as if an implicit quote has suddenly been wrapped around each
|> of "body" and "other"! Why did this happen? How can I get the effect
|> I intend?
You need to remember that the arguments to the macro-expansion
function are the *unevaluated* forms in the argument positions of
the macro call. So in your example modify-body-somehow is called
with 'body and 'other as arguments.
If you replace the LET statement with
(make-modified-function (equal 1 2) (stuff1 stuff2))
it will do what you want.
If you need to construct the function at run time, don't
use macros. ---Luigi
In article <·················@bowmore.harvard.edu>,
····@bowmore.harvard.edu (Wheeler Ruml) wrote:
> A question which should be easy to answer, but has me stumped:
>
> Given a list which looks like Lisp code, how does one create a
> function with a modified version of that code as its body?
>
> Currently, I use:
>
> (defmacro make-modified-function (body arg-for-modifier)
> `#'(lambda (arg)
> ,(modify-body-somehow body arg-for-modifier)))
>
> [...]
I'm surprised that noone has gone back to the basics and suggested
something like the following:
(in-package "CL-USER")
(defvar *compile-functions?* nil
"Should MAKE-FUNCTION create compiled or interpreted functions?")
(defun make-function (lambda-list &rest body-forms)
"Creates a compiled or interpreted function having the given lambda list
and body."
(let ((lambda-expression `(lambda ,lambda-list ,@body-forms)))
(if *compile-functions?*
(compile nil lambda-expression)
(coerce lambda-expression 'function))))
Now that you have a generic creator of run-time functions, you can do
pretty much whatever you want. For the particular use cited, you can
write:
(defun make-modified-function (body arg-for-modifier)
(make-function '(arg) (modify-body-somehow body arg-for-modifier)))
Philip L. Stubblefield 415/325-7165
Rockwell Palo Alto Laboratory ····@rpal.rockwell.com