From: Keats <ke...@su...> - 2003-07-26 22:06:28
|
Marc, #macro's don't have a separate context, but #templets do, so you could easily do what you are trying to do with a #templet/#eval. Check it out -- I haven't gotten any feedback on this yet. (I'm not trying to say it's better; it's just different. #macro's are generally faster while #templet's may be easier to understand.) Keats Brian Goetz wrote: >>I've just spent a long time tracking down an obscure template bug, caused >>by the non-intuitive way #macro works. > > >>...even though there is never an assignment to $fieldValue in the macro. >>This is caused by the usage of the variable $value inside the macro, which >>is inadvertently clashing with the global scope $value - it is of course >>supposed to be a local variable, which is not supported by #macro. > > > You can't possibly think that its a local value, could you? Have you > ever written a macro in C? The semantics of WM's #macro are totally > modeled on that. THey are expanded at runtime. There are no > macro-scoped variables, or any other sort of local variables in WM. > > Every well-written C macro uses names like __value instead of value to > avoid capture problems. > > I agree that this is a more subtle capture problem than usual, but the > core of thie problem is that any macro that does this: > > #set $value = "blah" > > is asking for problems. > > The reason for the pass-by-reference is that macro expansion should be > transparent -- variables that are passed in as l-values can be > l-values in the macro body. Otherwise, macros would just be > functions. > > So you can do this: > > #macro mset($a, $b) { > #set $a = $b > } > > and the expected thing happens. By the way, the above is immune to > this particular capture problem: > > #macro mset($a, $b) { > #set $a = $b > } > > #set $a=1 > #set $b=2 > #set $c=3 > #set $d=4 > #mset($c, $d) > > After execution, $a will _not_ be modified -- beacuse $a in the mset > body is a macro formal, not the $a in the global context. The result > will be a=1, b=2, c=4, d=4. So you can use any names you like for > macro formals without fear of capture. > > BTW, macros do all sorts of cool compile time optimization, too, since > they are expanded against the build context. So with > > #const debug=false > #macro foo { > #if (debug) { blah blah blah } > } > > ... > > Ya ya #foo ya > > the #foo reference gets totally eaten at compile time and doesn't even > make it into the compiled template -- it is totally optimized away. > > >>I'm not sure what we can do about this. I mistakenly thought #macro would >>have a separate context for its arguments, and as such changes to an outer >>variable would not suddently change the value of a differently named >>parameter to the macro. > > > Nope, not how it works, nor how it was intended to work -- otherwise > you couldn't have macros that modified their arguments. > > >>So, is this a bug or a "feature"? > > > Feature. Just like C macros. If you intend to have local variables, > name them in such a way as to never conflict, just like in C. > > Macro-local variables would be nice -- want to add them? > > > ------------------------------------------------------- > This SF.Net email sponsored by: Free pre-built ASP.NET sites including > Data Reports, E-commerce, Portals, and Forums are available now. > Download today and enter to win an XBOX or Visual Studio .NET. > http://aspnet.click-url.com/go/psa00100003ave/direct;at.aspnet_072303_01/01 > _______________________________________________ > Webmacro-devel mailing list > Web...@li... > https://lists.sourceforge.net/lists/listinfo/webmacro-devel > |