Thank you for your response and clarifying things, Simon.
| using x val body = [| do { (var x) <- val; body; (var x).Dispose () } |] | // x is of type string | | [| \y -> do { $(using "x" [| x |]); f y |] | | wouldn't work, and one would have to use gensym by his own to get
expected
| sematics.
I'm sorry, I didn't understand this at all. What is 'using x val body'? What is .Dispose()? Not Template Haskell certainly.
Well, it supposed to be a function, which takes 'x' (of type string), 'val' and 'body' (being expressions) and creates code which does: - define local variable of name 'x' initialized with 'val' - execute 'body' (it is assumed to have occurrences of 'x' inside, which should be captured by local 'x' - disposes 'x' (it has method 'Dispose', so I think its Haskell counterpart would be calling function 'Dispose' on 'x') This can be implemented in TH with (dyn "x") which you mentioned, but if 'body' is itself passed from another context and 'x' is introduced in f body = [| using "x" Foo $( [| do { dosomething x; body } |] ) |] then some external 'x' in original 'body' might get catched by dynamic binding, which is not hygienic behavior. I'm aware that this can be workaround with manually creating 'x' with newName and using this Name. Our decision to bind variables after macros expansion makes it possible to handle such cases in other way. There are opposite design goals, and I clearly see advantage of TH's one - bind to what you can see, before any expansion. Nevertheless we will try another approach and experiment with such system. To make myself more clear, I will give another example. Unfortunately I'm not able to easily write Haskell counterpart, so I will try to describe what I mean in syntax of our system. (It's more similar to C# / Ocaml, where meta-functions are tagged explicitly at definition, but used like ordinary functions. Quotations are constructing code <[ e_1; e_2; ... ]>, while $ splices value of meta-expressions into enclosing quoted code). We have a following macro macro @for (init, cond, change, body) { <[ $init; def loop () : void { when ($cond) { $body; $change; loop() } }; loop (); ]> } It can be used e.g. for (mutable i <- 0; i < 10; i <- i + 1, printf ("%d\n", i)) If we put it into quotation <[ for (mutable i <- 0; i < 10; i <- i + 1) printf ("%d\n", i) ]> we would not find bindings for 'i' - definition of local 'i' is just parameter of function call, so other parameters are not in its scope and compilation of this quotation would fail. It's quite inconsistent with writing 'for' in plain code, where binding is done after its expansion. This and other examples made us consider binding always after expansion and handling hygiene in other way. This also shifts some error messages to next compilation stage, as you describe in notes.
As I say above, TH supports both pre-expansion binding (via plain mentions of a variable), and post-expansion biding (via "dyn"). Whatever you choose to do, let me encourage you to give it a formal description.
This needs good documentation for sure, as there are many contradictory intuitions at field of names binding. We are trying to design system as easy to use and understand as possible. One again thanks for pointing me revised notes and arguments behind your design. It was quite useful to see more examples and problems that can araise. Kamil Skalski Nemerle developer - http://nemerle.org