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

From: Matthias Felleisen (matthias at ccs.neu.edu)
Date: Wed Aug 12 10:42:07 EDT 2009

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



Posted on the users mailing list.