From: Brian G. <br...@qu...> - 2003-04-19 18:37:19
|
Marc; I'm afraid you've made a fundamental error in assumption about what #macro is for and how it works. What you describe is NOT a bug -- it illustrates its intended behavior. Webmacro templates processed twice -- once at parse time (this is called building), which produces a parse tree of sorts, and once at the time the template is expanded (run time.) Here's the key: MACROS ARE EXPANDED ENTIRELY AT BUILD TIME. This is why the ordinary #include doesn't pick up #macro definitions -- they're not in the template any more. WM macros are almost EXACTLY like C #defines. They are expanded entirely at compile time. However, many WM directives can be optimized away at compile time if their arguments are all compile time constants, which makes WM macros more powerful than C #defines, but which might also confuse you into thinking that they are run-time constructs. WM macros can call themselves and other macros -- as long as we can reach a base case at compile time. Example: #macro countdown($n) { #if ($n > 0) { $n #countdown($n-1) } } #countdown(5) This will expand, at compile time, to: 5 4 3 2 1 Try it! #macro was never designed to be a run-time template-function facility. I'm really sorry you assumed they were, and built a whole structure around them, but this is not a BUG in #macro -- its an attempt to use it _way_ beyond its designed purpose. > Here, I've tightened up the example a bit, and made it so #visitChildren > does not call itself directly - to deflect accusations regarding the > inability of a #macro to build itself given that it calls itself and hence > cannot hope to complete. Still it doesn't work, but I suspect still for > this reason, due to the way macros are built internally. It doesn't work because #macro was not designed to do this. > At the very least recursion, if it cannot be supported, should be > trapped and an exception thrown before your servlet log becomes > 500KB in one second! If WM had a #loop directive (btw, see the mail archives for why we don't!), this would be like saying "At the very least, WM should determine at compile time whether the user has coded an infinite loop." First of all, this is not "very least" behavior (does any system?), and second of all, its provably impossible. As you point out in your example, simply finding instances of a-calls-a is not enough to find all the cases. Macros which call other macros, which is a feature at the very periphery of its functionality in terms of anticipated usage, is a dangerous feature with limited usefulness (cool examples like #countdown aside.) Use such features at your own risk. Its not inherently a bug for macros to call each other or themselves -- but you must use it very carefully. > However, I can't believe that we can't support macro > recursion. Without it, any kind of DOM/XML based processing in WM > templates is pretty much impossible / extremely ugly (using > recursive #includes). I'm really sorry you thought thats what we had in mind when we built #macro, but it wasn't. You're right, you can't do it with #macro. I'm sorry you thought you could. The WM #macro facility was designed to work like the C #define facility. And that's still pretty damn useful! |