[plt-scheme] Creating new syntax for decision tables

From: Robby Findler (robby.findler at gmail.com)
Date: Fri Feb 9 09:26:08 EST 2007

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
> > > >
> > > >
> > >
> >
>

Posted on the users mailing list.