[racket] Macros and dynamically generating identifiers

From: Sean McBeth (sean.mcbeth at gmail.com)
Date: Fri May 3 13:58:19 EDT 2013

Wow, section 4 is exactly, almost word for word, what I was trying to do.
This is a great resource.


On Fri, May 3, 2013 at 7:35 AM, Philipp Dikmann <philipp at dikmann.de> wrote:

>  You might have already read it, but I also found the guide "Fear of
> Macros" by Greg Hendershott incredibly helpful in understanding them,
> especially considering things like with-syntax and format-id:
> http://www.greghendershott.com/fear-of-macros/index.html
>
>
> On 03.05.13 04:57, Sean McBeth wrote:
>
> I think I get it just from reading it (in bed,  on the phone, annoying the
> wife). I had tried to do almost this very thing with datum->syntax at one
> point, but I had put the quotesyntax on datum->syntax, not on id directly.
> I don't understand why that would make a difference, it seems like it is
> similar to doing (list 'a 'b) instead of '(a b)... oh, nope, now I get it.
> It specifically *is* similar, except my second example should have been
> '(list a b).
> On May 2, 2013 10:38 PM, "Sean McBeth" <sean.mcbeth at gmail.com> wrote:
>
>> Aaah, man. Thanks. Shutdown the pc for the night so u will try tomorrow.
>> On May 2, 2013 10:35 PM, "Jay McCarthy" <jay.mccarthy at gmail.com> wrote:
>>
>>> You were close to what you want. Here's a version with a nice utility
>>> and then the underlying machinery that makes it:
>>>
>>> #lang racket
>>> (require (for-syntax racket/syntax))
>>>
>>> (define-syntax (double-define stx)
>>>   (syntax-case stx (double-define)
>>>     [(_ id val1 val2)
>>>      (with-syntax ([id-1 (format-id #'id "~a-1" #'id)]
>>>                    [id-2 (datum->syntax
>>>                           #'id
>>>                           (string->symbol
>>>                            (format "~a-2"
>>>                                    (syntax->datum
>>>                                     #'id))))])
>>>        #'(begin (define id-1 val1)
>>>                 (define id-2 val2)))]))
>>>
>>> (double-define id 3 7)
>>> (displayln id-1)
>>> (displayln id-2)
>>>
>>> On Thu, May 2, 2013 at 8:29 PM, Sean McBeth <sean.mcbeth at gmail.com>
>>> wrote:
>>> > Hi there!
>>> >
>>> > I'm pretty new to Racket, though not the basic concepts of functional
>>> > programming [1] Maybe I don't need macros here at all, but it seemed
>>> like
>>> > the right sort of lever when I first started, but now I'm pretty
>>> stuck[2]
>>> > and I don't understand enough about the macro system yet to be able to
>>> > figure this out.
>>> >
>>> > Basically, I'm trying to make a database migration tool + relational
>>> mapper.
>>> > I'd like to be able to define my tables in an abbreviated Racket
>>> syntax and
>>> > use the definition to generate everything from the create-table SQL
>>> scripts,
>>> > a few, basic CRUD-scripts-for-all-columns to structs that will mirror
>>> a full
>>> > table row when processing the query results.
>>> >
>>> > Right now, the table definition looks like this:
>>> >
>>> > (define-table tickets get-all-tickets
>>> >  ([ticket_id serial primary-key]
>>> >   [priority int nullable] ;; I believe in making not-null the default
>>> case
>>> >   [description (varchar max)]
>>> >   [finished_on datetime (default "9999-12-31 23:59:59.999")])
>>> >
>>> > And this is pretty easy to parse into some "table" structs that
>>> describe
>>> > everything fairly sufficiently[3]:
>>> > https://gist.github.com/capnmidnight/5506674
>>> >
>>> > Now, my sticking point is that I don't want to have explicitly define
>>> that
>>> > "get-all-tickets" identifier. I notice that, in my creating the
>>> "column"
>>> > struct, I've received a number of procedures for the constructor and
>>> field
>>> > accessors, all given a prefix of "column" for their identifier. So at
>>> first
>>> > glance, it seems like there are forms like struct that are capable of
>>> > dynamically defining identifiers.
>>> >
>>> > So, I stepped into the definition for struct and tried to make sense
>>> of it,
>>> > but the best I could figure out was that struct used syntax-case
>>> instead of
>>> > syntax-rules. It was a bit of a hair-ball for me, I couldn't suss out
>>> the
>>> > cross references, and at least at this late of an hour I'm having
>>> trouble
>>> > understanding the documentation on syntax-case.
>>> >
>>> > Specifically, I tried to do something like:
>>> >
>>> > (define-syntax (double-define stx)
>>> >   (syntax-case stx (double-define)
>>> >     [(_ id val1 val2)
>>> >      #`(begin (define id-1 val1)
>>> >               (define id-2 val2))]))
>>> >
>>> > (double-define id 3 7)
>>> > (displayln id-1) ;; error "id-1 unbound identifier"
>>> > (displayln id-2)
>>> >
>>> > I then tried something like:
>>> >
>>> > (define-syntax (double-define stx)
>>> >   (syntax-case stx (double-define)
>>> >     [(_ id val1 val2)
>>> >      (with-syntax ([id-1 #'(string->symbol (format "~a-1" id))] ;;
>>> error
>>> > "define: not an identifier, identifier with default, or keyword for
>>> > procedure argument"
>>> >                    [id-2 #'(string->symbol (format "~a-2" id))])
>>> >        #'(begin (define id-1 val1)
>>> >                 (define id-2 val2)))]))
>>> >
>>> > (double-define id 3 7)
>>> > (displayln id-1)
>>> > (displayln id-2)
>>> >
>>> > Clearly, not correct.
>>> >
>>> > I could make the table struct into a table class and then just define a
>>> > get-all method that does what I want, but that kind of feels like
>>> giving up
>>> > and I'm more interested in using this to learn more about using
>>> macros, as
>>> > it has already done for me.
>>> >
>>> >
>>> >
>>> > [1] Functional C# is something of a job safety program of mine :P
>>> >
>>> > [2] i.e. been banging my head against the desk for the last 6 hours. I
>>> have
>>> > gotten pretty comfortable with syntax-rules though, so it wasn't a
>>> complete
>>> > waste.
>>> >
>>> > [3] This isn't the final form, but I'm just pushing some code around
>>> to try
>>> > to get the basic concepts working. For example, the get-all-tickets
>>> > procedure wouldn't just return the query, it'd eventually execute it
>>> and
>>> > return the results.
>>> >
>>> > ____________________
>>> >   Racket Users list:
>>> >   http://lists.racket-lang.org/users
>>> >
>>>
>>>
>>>
>>> --
>>> Jay McCarthy <jay at cs.byu.edu>
>>> Assistant Professor / Brigham Young University
>>> http://faculty.cs.byu.edu/~jay
>>>
>>> "The glory of God is Intelligence" - D&C 93
>>>
>>
>
> ____________________
>   Racket Users list:
>   http://lists.racket-lang.org/users
>
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.racket-lang.org/users/archive/attachments/20130503/7b62256a/attachment.html>

Posted on the users mailing list.