[racket] Macros and dynamically generating identifiers

From: Philipp Dikmann (philipp at dikmann.de)
Date: Fri May 3 07:35:30 EDT 2013

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 
> <mailto: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
>     <mailto: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 <mailto: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 <mailto:jay at cs.byu.edu>>
>         Assistant Professor / Brigham Young University
>         http://faculty.cs.byu.edu/~jay <http://faculty.cs.byu.edu/%7Ejay>
>
>         "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/27fb64b4/attachment-0001.html>

Posted on the users mailing list.