[plt-scheme] Creating new syntax for decision tables
On 2/9/07, Andrew Gacek <andrew.gacek at gmail.com> wrote:
> Thanks for the quick and helpful responses. Jacob's code is very
> similar to how I expected this macro to look. I was also able to add
> some basic error checks as well
>
> (define-syntax table
> (syntax-rules (:)
> [(table (e : c1 c2 ...) ...)
> (or (and (clause-transform c1 e) ...)
> (table (e : c2 ...) ...))]
> [(table (e :) ...)
> #f]
> [(table (e1 : c1 c2 ...) (e2 :))
> (error "Table mismatch for rows"
> (quote e1) 'and (quote e2))]
> [(table (e1 :) (e2 : c1 c2 ...))
> (error "Table mismatch for rows"
> (quote e1) 'and (quote e2))]))
>
> (define-syntax clause-transform
> (syntax-rules (T F *)
> [(clause-transform T e) e]
> [(clause-transform F e) (not e)]
> [(clause-transform * e) #t]
> [(clause-transform other e)
> (error "Unknown flag: " (quote other))]))
>
> Now it checks that each row has the same number of flags and that each
> flag is either T, F, or *.
These error checks are at runtime, but you're checking static properties.
Also, if you raise syntax errors during macro expansion, you get
precise source locations.
> I have two remaining questions for this example:
>
> 1. If I want to prevent the expressesions on the left side of the
> colons from being evaluated more than once, what is the best way to do
> this? My initial thought it to make another macro which passes those
> expressions into a function call so that they are evaluated just once.
If you want to use syntax-rules, rename your macro above to
"table-but-where-the-expressions-are-variables" and have table expand
into a let that uses that macro.
> 2. Is there a way to show the expansion of these macros? So that I can
> see what expression is being generated for a particular table.
Try the macro stepper. I'm not sure if it was in 360, but it is in the
nightly builds (which are generally stable).
> Thanks,
> Andrew
>
> On 2/8/07, Robby Findler <robby.findler at gmail.com> wrote:
> > Oh! Nice use of the ellipses.
> >
> > That trick can be adapted to my verison below to get rid of the use of
> > transpose (if you want to improve the error reporting, you'll probably
> > want to use the syntax-case version).
> >
> > Robby
> >
> > On 2/8/07, Jacob Matthews <jacobm at cs.uchicago.edu> wrote:
> > > This can also be done pretty nicely using syntax-rules. Here's a
> > > version that uses only pattern matching:
> > >
> > > (module a mzscheme
> > >
> > > (define-syntax table
> > > (syntax-rules (:)
> > > [(table (e : c1 c2 ...) ...)
> > > (or (and (clause-transform c1 e) ...)
> > > (table (e : c2 ...) ...))]
> > > [(table (e :) ...)
> > > #f]))
> > >
> > > (define-syntax clause-transform
> > > (syntax-rules (T F *)
> > > [(clause-transform T e) e]
> > > [(clause-transform F e) (not e)]
> > > [(clause-transform * e) #t])))
> > >
> > >
> > > Examples:
> > >
> > > > (let ([a #t] [b #f] [c #t])
> > > (table
> > > (a : T T T)
> > > (b : T F *)
> > > (c : T F F)))
> > > #f
> > > > (let ([a #t] [b #f] [c #t])
> > > (table
> > > (a : T T *)
> > > (b : T F *)
> > > (c : T F F)))
> > > #f
> > > > (let ([a #t] [b #f] [c #t])
> > > (table
> > > (a : T T *)
> > > (b : * F *)
> > > (c : T F F)))
> > > #t
> > >
> > >
> > > Notes:
> > > - not thoroughly tested
> > > - as written it will evaluate each e several times, this can be
> > > changed easily enough
> > > - of course there's no syntax error checking
> > >
> > > -jacob
> > >
> > >
> > >
> > > On 2/8/07, Robby Findler <robby.findler at gmail.com> wrote:
> > > > Oops, left in a silly bug. Here you go:
> > > >
> > > > (module m mzscheme
> > > >
> > > > (define-syntax (table stx)
> > > > (syntax-case stx (:)
> > > > [(_ clauses ...)
> > > > (let* ([transpose (λ (l) (apply map list l))]
> > > > [rewrite-clauses
> > > > (λ (clause)
> > > > (syntax-case clause (:)
> > > > [(var : tfs ...)
> > > > (map
> > > > (λ (tf)
> > > > (syntax-case tf (T F)
> > > > [T #'var]
> > > > [F #'(not var)]
> > > > [* #'#t]))
> > > > (syntax->list (syntax (tfs ...))))]))])
> > > > (with-syntax ([((item ...) ...)
> > > > (transpose (map rewrite-clauses
> > > > (syntax->list (syntax (clauses
> > > > ...)))))])
> > > > #'(or (and item ...) ...)))]))
> > > >
> > > > (λ (a b c)
> > > > (table
> > > > (a : T T F)
> > > > (b : F * F)
> > > > (c : * F T))))
> > > >
> > > > _________________________________________________
> > > > For list-related administrative tasks:
> > > > http://list.cs.brown.edu/mailman/listinfo/plt-scheme
> > > >
> > > >
> > >
> >
>