[plt-scheme] Creating new syntax for decision tables
On 2/10/07, Daniel Yoo <dyoo at cs.wpi.edu> wrote:
>
> Another similar approach might be to do what you're thinking, building a
> function that remembers what it returns, so that we avoid evaluation
> unless absolutely necessary.
For this case, DELAY and FORCE work nicely. A small refinement only
optionally uses them if the value is an application:
(define-syntax table
(syntax-rules ()
((table e ...)
(table-let () () e ...))
))
(define-syntax table-let
(syntax-rules (:)
((table-let (vars ...) (rows ...) ((app ...) : c1 ...) e2 ...)
(table-let (vars ... (tmp (delay (app ...)))) (rows ... ((force tmp) : c1 ...)) e2 ...))
((table-let (vars ...) (rows ...) (x : c1 ...) e2 ...)
(table-let (vars ...) (rows ... (x : c1 ...)) e2 ...))
((table-let (vars ...) (rows ...))
(let (vars ...)
(table-expand rows ...)))
))
(define-syntax table-expand
(syntax-rules (:)
;; note error checking should come before default actions
[(table-expand (e1 : c1 c2 ...) (e2 :) e3 ...)
(error "Table mismatch for rows"
(quote e1) 'and (quote e2))]
[(table-expand (e1 :) (e2 : c1 c2 ...) e3 ...)
(error "Table mismatch for rows"
(quote e1) 'and (quote e2))]
[(table-expand (e : c1 c2 ...) ...)
(or (and (clause-transform c1 e) ...)
(table-expand (e : c2 ...) ...))]
[(table-expand (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]
[(clause-transform other e)
(error "Unknown flag: " (quote other))]))
The laziness is needed if you want any kind of short-circuit logic in
the table, since unlike AND or OR, values can be referred to from
multiple execution paths.
--
Alex