On Fri, Jul 29, 2011 at 12:44 PM, Maurizio Giordano <[email protected]> wrote: > On Fri, 2011-07-29 at 12:20 -0400, Carl Eastlund wrote: >> >> There is one module called "multiset", but all of its definitions are >> executed twice because your program uses them in two different phases: >> once at run-time and once at compile-time. That means >> there are two different mset types with two different constructors and >> two different mset? predicates. Call the run-time versions mset.1 and >> mset?.1, and the compile-time versions mset.2 and mset?.2. Similarly, >> you have print-type.1 and print-type.2 at run-time and compile-time. >> >> Your custom reader produces an mset.1 value. Your macro calls >> print-type.2 which checks mset?.2, and mset?.2 produces #false when >> given an mset.1 value. The code your macro produces, however, calls >> print-type.1, which checks mset?.1, and that produces #true (I'm using >> the new long-form names of #f and #t for readability). So no >> information is being lost -- it's just that there are two versions of >> everything running around, and they cannot be mixed and matched. > Now it is perfectly clear to me. > thanks a lot. >> >> >> Are you sure you want to put mset values in as literal syntax? That >> leads to all sorts of odd behavior -- for instance, the contents of >> those msets will need to be syntax at compile-time if they are to >> contain expressions, but non-syntax at run-time if they are to contain >> useful values. The expansion system will not do this plumbing for >> you. You'll get a lot more "bang for your buck" if you instead just >> use a match expander as both a pattern to recognize msets and a >> constructor to build them. This avoids all issues of crossing phase >> boundaries, because the compile-time code acts entirely by recognizing >> identifier bindings, and does not have to know about the >> representation of msets at all. > The "templates" I generate at compile-time in the macro are some sort of > a syntax tree: > > An example: > the macro (three) inputs: < (1 x), 2 > x 3 > will generate an hash like this: > > #hash ((mset . #hash((list . #hash((integer . 1) > (symbol . x))) > (symbol . x))) > (symbol . x) > (integer . 3)) > > By using this nested hashtable, the "inject-code" function will > produce a (recursive) pattern matchers code to be included in the lambda > code generated by the macro. Symbols in the input are not evaluated, > they will are considered identifiers to be bound (and unified) > during the pattern matching. > > Therefore, I think I am not using the mset values at compile-time. > I simply parse the macro inputs to generate a sort of syntax tree > (i.e. the hashtable).
You are not using them as outputs, but you are using them as inputs. Even that is problematic, exactly as you have seen. I suggest writing a macro using only standard syntax objects containing lists, strings, symbols, and numbers for both input and output if at all possible. This will save a lot of trouble. Using hash tables in syntax objects can work, but even that brings up some tricky issues. I find it is almost always better to consume and produce code that refers to or produces complex data types, rather than code actually represented as complex data types. --Carl _________________________________________________ For list-related administrative tasks: http://lists.racket-lang.org/listinfo/users

