[plt-scheme] macros that expand into top-level definitions with computed names

From: Lee Spector (lspector at hampshire.edu)
Date: Wed Aug 12 11:26:23 EDT 2009

> The above conflates two different things:
> -- partial-name is a variable that maps to the run-time value "yours"
> -- def is new syntax, which like definitions in mathematics, is  
> removed before run-time
> We call these phases.
>
> Now, if you happen to know the value of partial-name when you  
> expand, this is no problem. Just refer to partial-name in the macro  
> (roughly speaking). If you are figuring out these names at run-time,  
> you're looking at an extremely dynamic problem and macros may not be  
> your friend.
>
> (Indeed, I don't know how CL would cope with this issue. When you  
> compile the code, macros go away, too.)
>


My mistake -- after some of the recommended reading I remembered macro- 
related issues that I had forgotten about and realized that my  
imagined defmacro solution in Common Lisp wouldn't work either! Thanks  
for your clarification on why this is, and for your patience.

But whether or not there's a CL macro-based solution (I'm still not  
sure) the eval-based approach does indeed do the sort of thing I want  
in CL. Here I define def as a function and quote the other arguments  
in the call to def, which is fine for my purposes:

(defun def (name arg body)
   (eval `(defun ,(intern (concatenate 'string "MY-" name))  
(,arg) ,body)))

(setq partial-name "YOURS")

(def partial-name 'x '(sqrt x))

(MY-YOURS 4) => 2

Again, in PLT I can use eval in a similar way to make definitions of  
functions with computed names work for subsequent calls in the  
interactions pane, but not for calls in the same file. I thought this  
was a clue that I might try putting the definitions in another file/ 
module, but then I see problems producing the necessary (provide ...)  
form. Is there a way around this?

In fact I DO know partial-name at compile time, or at least at what  
should be compile time for the code that will call the resulting  
functions. That is, I'm not going to be doing things like taking input  
from the user that gets turned into function names. But I want to do  
some computation to produce the function names and definition bodies  
since these will be combinatorial products of lists of symbols. Is  
there a way to do this either using PLT macros or module instantiation  
phases?

I realize that I could write one program that creates all of the  
definitions (along with module-related forms) and writes them to a  
file, and then used the resulting file as source code. But it would be  
nice to avoid that.

Thanks again,

  -Lee




On Aug 12, 2009, at 10:42 AM, Matthias Felleisen wrote:

>
> On Aug 11, 2009, at 11:39 PM, Lee Spector wrote:
>
>>
>> Thanks Matthias,
>>
>> That certainly is a different approach than defmacro! But it does  
>> seem to get me most of the way there and I think I could get the  
>> rest of the way (and maybe understand and appreciate more of what  
>> I've been reading in the Macros section of the reference) if I  
>> could see how to modify your example so that it evaluated its first  
>> argument, as in:
>>
>> (define partial-name "yours")
>>
>> (def partial-name x (sqrt x))
>>
>> (my-yours 4) => 2
>>
>> BTW this isn't for prefixing or suffixing per se -- it's for a  
>> version of a stack based language in which there are a bunch of  
>> types, a bunch of instructions that work the same way on all types  
>> but with different names and accessing different stacks, and I want  
>> to generate functions by looping over the two lists and executing a  
>> definition for each type/instruction pair. (These aren't PLT types,  
>> they're types in my language -- http://hampshire.edu/lspector/push.html 
>>  -- and I'm not interested at the moment in doing this in any way  
>> that depends on PLT types... I just want to be able to generate and  
>> execute definitions with computed names and bodies, which is  
>> something I often find handy in CL.)
>
>
> The above conflates two different things:
> -- partial-name is a variable that maps to the run-time value "yours"
> -- def is new syntax, which like definitions in mathematics, is  
> removed before run-time
> We call these phases.
>
> Now, if you happen to know the value of partial-name when you  
> expand, this is no problem. Just refer to partial-name in the macro  
> (roughly speaking). If you are figuring out these names at run-time,  
> you're looking at an extremely dynamic problem and macros may not be  
> your friend.
>
> (Indeed, I don't know how CL would cope with this issue. When you  
> compile the code, macros go away, too.)
>
> -- Matthias
>
>
>
>
>
>
>
>
>
>
>
>
>
>>
>> Thanks,
>>
>> -Lee
>>
>> On Aug 11, 2009, at 10:27 PM, Matthias Felleisen wrote:
>>
>>>
>>> Do you mean this kind of thing:
>>>
>>> #lang scheme
>>>
>>> (define-syntax (def stx)
>>> (syntax-case stx ()
>>>   [(_ f x body ...)
>>>    (identifier? (syntax f))
>>>    (let* ([f:sym (syntax-e (syntax f))]
>>>           [my-f:str (string-append "my-" (symbol->string f:sym))]
>>>           [my-f:sym (string->symbol my-f:str)]
>>>           [my-f:id (datum->syntax stx my-f:sym)])
>>>      #`(define #,my-f:id (lambda (x) body ...)))]))
>>>
>>> (def yours x (sqrt x))
>>>
>>> (my-yours 4)
>>>
>>> I recommend creating a module in your personal collects that  
>>> provides for adding prefixes and suffixes and importing it when  
>>> needed. It's in my standard collection
>>>
>>> -- Matthias
>>>
>>>
>>>
>>> On Aug 11, 2009, at 9:31 PM, Lee Spector wrote:
>>>
>>>>
>>>> I'm still transitioning from Common Lisp (thanks for all of the  
>>>> pointers so far) and I'm having trouble doing something that I  
>>>> could easily do with a CL macro.
>>>>
>>>> I'd like to write a macro (or whatever) that takes two strings  
>>>> and defines a function named with the symbol formed from  
>>>> interning the concatenation of the strings. For example if the  
>>>> arguments have the values "my-" and "function" in a particular  
>>>> call then I'd like the effect of the call to be the same as  
>>>> something like (define my-function <more stuff here>).
>>>>
>>>> This is straightforward using defmacro in CL, but looking through  
>>>> the section of the PLT reference on macros I don't see where to  
>>>> start.  In CL if I didn't know about defmacro, and if I didn't  
>>>> mind having my definitions evaluated in a null lexical  
>>>> environment, then I could hack it with eval. So with my new (but  
>>>> still minimal) understanding of eval and namespaces in PLT I  
>>>> tried this:
>>>>
>>>> -------
>>>> #lang scheme
>>>>
>>>> (define-namespace-anchor nsa)
>>>> (define ns (namespace-anchor->namespace nsa))
>>>>
>>>> (eval `(define ,(string->symbol (string-append "my-" "function"))
>>>>             (lambda () 'runs))
>>>>     ns)
>>>>
>>>> (my-function)
>>>> -------
>>>>
>>>> This doesn't work -- expand: unbound identifier in module in: my- 
>>>> function -- although if I get rid of the call to my-function in  
>>>> the definitions pane then it does compile and allow me to call my- 
>>>> function (which then does the right thing) in the interactions  
>>>> pane. But that's not good enough for my purposes.
>>>>
>>>> Of course this hack with eval is probably the wrong approach  
>>>> anyway -- it would be a bad way to do it in CL and I'm guessing  
>>>> that a completely different approach would be appropriate in PLT.  
>>>> And I think I'm just not seeing the right part of the PLT docs  
>>>> because of the differences in terminology.
>>>>
>>>> Can someone point me in the right direction on this?
>>>>
>>>> Thanks,
>>>>
>>>> -Lee
>>>>
>>>> --
>>>> Lee Spector, Professor of Computer Science
>>>> School of Cognitive Science, Hampshire College
>>>> 893 West Street, Amherst, MA 01002-3359
>>>> lspector at hampshire.edu, http://hampshire.edu/lspector/
>>>> Phone: 413-559-5352, Fax: 413-559-5438
>>>>
>>>> Check out Genetic Programming and Evolvable Machines:
>>>> http://www.springer.com/10710 - http://gpemjournal.blogspot.com/
>>>>
>>>> _________________________________________________
>>>> For list-related administrative tasks:
>>>> http://list.cs.brown.edu/mailman/listinfo/plt-scheme
>>
>> --
>> Lee Spector, Professor of Computer Science
>> School of Cognitive Science, Hampshire College
>> 893 West Street, Amherst, MA 01002-3359
>> lspector at hampshire.edu, http://hampshire.edu/lspector/
>> Phone: 413-559-5352, Fax: 413-559-5438
>>
>> Check out Genetic Programming and Evolvable Machines:
>> http://www.springer.com/10710 - http://gpemjournal.blogspot.com/
>>
>> _________________________________________________
>> For list-related administrative tasks:
>> http://list.cs.brown.edu/mailman/listinfo/plt-scheme

--
Lee Spector, Professor of Computer Science
School of Cognitive Science, Hampshire College
893 West Street, Amherst, MA 01002-3359
lspector at hampshire.edu, http://hampshire.edu/lspector/
Phone: 413-559-5352, Fax: 413-559-5438

Check out Genetic Programming and Evolvable Machines:
http://www.springer.com/10710 - http://gpemjournal.blogspot.com/



Posted on the users mailing list.