[racket] Problem with macro

From: Racket Noob (racketnoob at hotmail.com)
Date: Fri Aug 12 11:08:58 EDT 2011

Thank you, Neil.
 
I really appreciate your answer. I've just started programming with syntax-rules and I see now that I have lot to learn further about these scheme-way macros.
Unfortunately, i'm currently unable to produce this macro with syntax-rules or syntax-case.
 
But i have done it in classic, "old fasioned" way:
 
#lang racket
 
(require mzlib/defmacro (for-syntax racket))
 
(define-macro (automaton init-state transitions)
  (let* ([curr-state (gensym)]
         [make-transition (lambda (transition)
                            (let ([state (first transition)]
                                  [endstate (third transition)])
                              `((,state) (set! ,curr-state ,endstate) ,(if (eq? endstate 'END) 
                                                                           ''endstate
                                                                           ''ok))))]
         [make-state (lambda (state-def)
                       (let ([state-name (first state-def)]
                             [transitions (cddr state-def)])
                         `(,state-name
                           (lambda (symbol)
                             (case symbol
                               ,@(map make-transition transitions)
                               (else 'transition-error))))))])
    `(letrec ([,curr-state null]
              [END
               (lambda (symbol)
                 'read-past-end-error)]
              ,@(map make-state transitions))
       (set! ,curr-state ,init-state)
       (lambda (c)
         (,curr-state c)))))
 

(define mydfa
  (automaton start
             ((start : (c -> more))
              (more : (a -> more)
                      (d -> more)
                      (r -> END)))))
  

 
By the way, i have created stateful dfa purposely (by using variable curr-state as DFA's state) so that i can "feed" it with symbols, one by one, i.e.
 
> (mydfa 'c)
ok
> (mydfa 'a)
ok
> (mydfa 'd)
ok
> (mydfa 'r)
endstate
 
Shriram's approach (described here: http://www.cs.brown.edu/~sk/Publications/Papers/Published/sk-automata-macros/paper.pdf ) forces us to give input all in one take.
 
 
Racket Noob
 

> Date: Fri, 12 Aug 2011 10:22:18 -0400
> From: neil at neilvandyke.org
> To: racketnoob at hotmail.com
> CC: users at racket-lang.org
> Subject: Re: [racket] Problem with macro
> 
> 1. Without trying it, I'm pretty sure this particular syntax 
> transformation can be done in "syntax-rules", but I'm not certain it can 
> be done using only the power of "..." in "syntax-rules", without a 
> helper macro. Your life might be easier if you do this particular 
> transformation in "syntax-case" rather than "syntax-rules".
> 
> 2. If you use "syntax-rules" instead of "syntax-case", three tips: (1) 
> break it up into mutiple macros, so you can have secret recursive helper 
> macros that have arguments for lists of input that you haven't processed 
> and arguments for lists of output from that processing, such as for 
> assembling lists of "letrec" or "case" clauses; (2) instead of 
> "process-state", you can have your helper macros assemble some of the 
> ultimate code *bottom-up*, so that, for example, things like the 
> "letrec" clauses (or "case" clauses, or parts of "case" clauses) get 
> assembled first, and only after all the clauses are assembled do the 
> "letrec" and other unchanging stuff around them get assembled; and (3) 
> it's good to expand to "case"/"if"/"and"/"or" for control flow, but 
> avoid expanding to "cond", because it's syntactic-sugary, and you'd have 
> to worry about "else" and "=>" appearing in your macro input.
> 
> 3. You've picked a somewhat tricky macro for "syntax-rules" -- harder 
> than most "syntax-rules" macros you'll usually want to implement. But 
> once you can implement this macro, I think you'll then have the tools to 
> implement most any other "syntax-rules" macro you want to in the 
> future. If you get stuck on this one, try simpler ones that isolate a 
> single tricky part. For example, contrive a programming exercise of a 
> macro that's a thin veneer around "case", and implement your macro using 
> a recursive helper macro rather than "...", to assemble each "case" 
> clause, one clause per recursion step. (Or just use "syntax-case", and 
> be done with it.)
> 
> 4. Before you spend too much time writing a macro for that particular 
> transformation, you might want to experiment some more with that example 
> you gave of code you're trying to transform to. See whether your state 
> transitions can simply can use tail calls to your "letrec" bindings for 
> the state closures, so that you need neither the "curr-state" variable 
> not the "ok" and "endstate" values. That would be more 
> Racket-idiomatic, the compiler might be able to optimize the code 
> better, and it might make your macro easier to implement.
> 
> (Pardon the writing in enumerations, but someone erroneously put caf 
> coffee in the decaf coffee carafe.)
> 
> -- 
> http://www.neilvandyke.org/
 		 	   		  
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.racket-lang.org/users/archive/attachments/20110812/b53543c2/attachment.html>

Posted on the users mailing list.