At Mon, 16 Feb 2015 14:36:16 -0500, "Paul Ojanen" wrote: > I'm working on a macro that will have mutable state. > > [I'm new to macros in general, and I'm new to pattern matching in Racket and > all things related to syntax functions and objects. I'm also still learning > about macro expansion, compile time, run time, etc.]
In case you haven't looked at it already, this paper might be helpful: "Composable and Compilable Macros: You Want it When?" http://www.cs.utah.edu/plt/publications/macromod.pdf > I was surprised that the macro's state is empty when I try to interact with > it from the Interactions Window. Are all the compile/macro-expansion time > definitions redefined for the Interactions Window? Yes. Each compilation of a module starts with fresh compile-time state for any module that it imports, including a module's own state while the module is being compiled. The top-level (for interaction) acts as a kind of module for that purpose. > In the below Interactions Window dialogue, why does (acc) start referring to > a different hashtable than ht2? The compile-time part of the module is instantiated once when then module is compiled, and `(acc)` expands to a mutable hash table during that compilation. In other words, the compiled form of the module has a specific mutable hash table for the right-hand side of `ht2`, and it's the same hash table every time the module is instantiated. Using `(acc)` in the interactions window, however, gets you a hash table from a fresh compile-time instance of the module. The fact that `datum->syntax` accepts a mutable hash table is a hole Racket's separation of phases. We sometimes call the result "3-D syntax", because it creates a syntax object that can't be written as literal syntax. We haven't closed the hole, for various reasons, but you should avoid 3-D syntax for your sanity and so that various Racket tools (such as `raco make`) can work. As it turns out, constructing 3-D syntax with a mutable hash table can be particularly confusing, because the hash table will get coerced to an immutable hash table if the code is ever marshaled to bytes, such as in a ".zo" file. So, it will seem to work for slightly longer than 3-D syntax usually seems to work, but it really doesn't work. > Here's my stripped-down code: > > #lang racket > > (begin-for-syntax > (define ht (make-hash)) > ) > > (define-syntax (acc stx) > (syntax-case stx () > [(_ (f (fn x) body)) (begin > > ; Record what was defined within the acc block > (hash-set! ht > (syntax->datum (syntax fn)) > (syntax->datum (syntax body))) > > ; Define it in the real evironment > #'(f (fn x) body))] > > [(_) (datum->syntax #'acc ht)] ; see what's been recorded > )) > > ; Define a sqr function > (acc > (define (sqr2 x) (* x x)) > ) > > ; Try the sqr function > (sqr2 5) > > ; See what was recorded by the macro > (acc) > > ; Bind a run-time variable to the macro's hashtable > (define ht2 (acc)) > > --------Interactions Window dialogue > 25 > '#hash((sqr2 . (* x x))) > > (sqr2 5) > 25 > > (acc) ;the hashtable is empty > '#hash() > > ht2 ;no, it's not > '#hash((sqr2 . (* x x))) > > (acc (define (sqr3 x) (* x x))) > > (acc) > '#hash((sqr3 . (* x x))) > > ht2 > '#hash((sqr2 . (* x x))) > > ____________________ > Racket Users list: > http://lists.racket-lang.org/users ____________________ Racket Users list: http://lists.racket-lang.org/users

