[racket] Macros and dynamically generating identifiers

From: Sean McBeth (sean.mcbeth at gmail.com)
Date: Thu May 2 22:57:25 EDT 2013

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
>>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.racket-lang.org/users/archive/attachments/20130502/4dfdd4b0/attachment-0001.html>

Posted on the users mailing list.