[racket] Macros: "define" a variable with a transformed id
On 08/13/2010 03:46 PM, Christopher Bowron wrote:
> I'm trying to write a macro that takes in an id, and creates a
> variable with a name based on id, and adds a string based on id into a
> list.
>
> If I have (define-filter-category foo), I want it to add
> "CICategoryFoo" to the FILTER-CATEGORIES list as well as introduce a
> binding for the variable filter-category-foo. I have the part that
> adds the string to the list, but I do not know how to manipulate the
> id and introduce the variable. Can anyone shed some light on this for
> me? Thanks
>
The short answer is hygiene is preventing you from binding identifiers
created in the macro to escape the scope of the macro. You need to
unhygienically introduce the identifier you want either through
syntax-local-introduce or pass the original lexical context (from the
macro use) to datum->syntax.
Also you it looks like you are trying to munge the names of identifiers
in the second pattern of `define-filter-category', but you need those
functions to run at transformation time. Code won't run in a
syntax-rules, it just gets expanded and returned.
> What I have so far:
>
> (define FILTER-CATEGORIES empty)
>
> (define (id->category-string n)
> (define (camel-case str)
> (regexp-replace* #rx"-" (string-titlecase str) ""))
> (string-append "CICategory" (camel-case (symbol->string n))))
>
> (define (id->category-id n)
> (string->symbol (string-append "filter-category-" (symbol->string n))))
>
> (define-syntax define-filter-category
> (syntax-rules ()
> ((_ id string)
> (begin
> ;;; FIXME: also (define ,id string)
> (set! FILTER-CATEGORIES (cons string FILTER-CATEGORIES))))
> ((_ name)
> (define-filter-category
> (id->category-id (quote name))
> (id->category-string (quote name))))))
>
>
> (define-filter-category distortion-effect)
> (define-filter-category ...)
>