> Yes, compatibility was and is a goal, but with limited resources, > continuing support for implicit scoping in macros didn't make the cut.
Ok. Are there any BC corner cases other than nested macros I should be aware of? I could not really find the No-BC notification you had mentioned. >> * When scopes of the same type are nested make the parent Scope >> available through the child (e.g. $foreach.parent or >> $foreach.topmost). Thanks. So, with macro.provide.scope.control =true scoping behavior should stay the same, and I'd have to explicitly use scope handles to reach different scopes, like $mymacroname.parent for example, or $macro.parent. Is this correct? Thanks Boris On Mon, Apr 30, 2012 at 5:08 PM, Nathan Bubna <nbu...@gmail.com> wrote: > On Mon, Apr 30, 2012 at 1:06 PM, Boris Partensky > <boris.parten...@gmail.com> wrote: >> I am seeing 3 bullet points there pertinent to this issue and all 3 >> seem to indicate that being compatible was the intention there, or am >> I wrong ? The way I read #2 and #3 is that the parent scope should >> only be available if I explicitly specify the scope I want (parent or >> topmost or replaced). > > Yes, compatibility was and is a goal, but with limited resources, > continuing support for implicit scoping in macros didn't make the cut. > >> * For performance and compatibility these are all off by default, >> *except* for $foreach. The others may be enabled by setting a velocity >> property like:macro.provide.scope.control = true > > "off for compatibility" here means reduced chance of squashing > someone's previous $macro or $template var, or more realistically $foo > when there is a body macro call #foo > >> * When scopes of the same type are nested make the parent Scope >> available through the child (e.g. $foreach.parent or >> $foreach.topmost). > > $<scope>.parent is always and only made available when there actually > is an explicit parent scope provided. e.g. > > #foreach( $a in $b ) > #foreach( $c in $d ) > $foreach.parent here == $foreach.topmost > #end > $foreach here == $foreach.topmost > #end > > Think parent and topmost as ways to navigate the scope stack, which > only exists when <scope>.provide.scope.control = true > >> * When a Scope reference overrides an existing reference that is not a >> Scope, make it available through the Scope (e.g. $foreach.replaced). > > $<scope>.replaced is not a parent scope, but is 'bar' in the example: > #set($foo='bar') #@foo $foo.replaced #end > > This is a workaround for incompatibilities/migrations/etc. It doesn't > provide any compatibility with the older implicit system of scoping. > >> On Mon, Apr 30, 2012 at 3:51 PM, Nathan Bubna <nbu...@gmail.com> wrote: >>> http://velocity.apache.org/engine/devel/changes-report.html#a1.7 >>> >>> On Mon, Apr 30, 2012 at 12:37 PM, Boris Partensky >>> <boris.parten...@gmail.com> wrote: >>>> No problem, thanks for making things clear. >>>> >>>> << we decided to forego it and notify users of the non-BC change when >>>> we released 1.7. >>>> >>>> which notification are you referring to? Wonder if there is something >>>> else in there I am not aware of. >>>> >>>> >>>> On Mon, Apr 30, 2012 at 2:34 PM, Nathan Bubna <nbu...@gmail.com> wrote: >>>>> Congratulations, Boris. You are the corner case we feared. :-/ We >>>>> knew when we went ahead with this that providing a migration path >>>>> would be difficult. We knew most users didn't have extreme numbers of >>>>> macros and hoped that those who didn't frequently nest them, in part >>>>> because of the complexities of heavy scoping in a language that often >>>>> treated scoping as a second-class feature, and in part because of the >>>>> performance issues macros had prior to 1.6. #parse, >>>>> VelocityLayoutServlet and even custom tools, which lack the implicit >>>>> scoping support, tended to be more performant and encouraged for >>>>> simplifying complicated tools. Considering those things and the >>>>> difficulty of implementing a BC switch for implicit scoping, we >>>>> decided to forego it and notify users of the non-BC change when we >>>>> released 1.7. >>>>> >>>>> Sorry. It sounds like it's going to take some legwork to upgrade in >>>>> the cases where you nested your macros. >>>>> >>>>> On Mon, Apr 30, 2012 at 11:16 AM, Boris Partensky >>>>> <boris.parten...@gmail.com> wrote: >>>>>> Yep, I am afraid we do set globals from within macros... >>>>>> >>>>>> On Mon, Apr 30, 2012 at 2:05 PM, Nathan Bubna <nbu...@gmail.com> wrote: >>>>>>> Can you set velocimacro.context.localscope = true or is it important >>>>>>> for your system to be able to #set global stuff from within macros? >>>>>>> >>>>>>> On Mon, Apr 30, 2012 at 10:50 AM, Boris Partensky >>>>>>> <boris.parten...@gmail.com> wrote: >>>>>>>> Thanks Nathan, I think I do get the whole scoping idea, but my >>>>>>>> understanding was that one of the reasons to turn all scoping off by >>>>>>>> default (and have those properties to begin with) was to provide >>>>>>>> backward compatibility - as in: I upgrade to 1.7 and then I start >>>>>>>> turning on all those nice bells and whistles and use scopes and what >>>>>>>> not. Not so seems like? I also find somewhat strange that a a formal >>>>>>>> argument to a macro takes precedence and overwrites a global variable >>>>>>>> with the same name. How would one go about upgrading existing systems? >>>>>>>> We have roughly 1900 macros, big chunk of those are nested... Maybe I >>>>>>>> am misunderstanding something, but this issue makes it almost >>>>>>>> impossible to upgrade (at least for us). >>>>>>>> >>>>>>>> >>>>>>>> Thanks >>>>>>>> Boris >>>>>>>> >>>>>>>> On Mon, Apr 30, 2012 at 12:55 PM, Nathan Bubna <nbu...@gmail.com> >>>>>>>> wrote: >>>>>>>>> Yeah, it was intended, and part of an overall move toward >>>>>>>>> fixing/simplifying Velocity's variable scoping, avoiding the >>>>>>>>> complexities and costs (performance, yes, but mostly time/brainpower >>>>>>>>> for users and devs alike) of more programming language type behavior. >>>>>>>>> Velocity has long aspired to be a straightfoward template engine and >>>>>>>>> avoid being a complete scripting language. (Implicit) variable >>>>>>>>> scoping, as seen in 1.5, was seen as a necessary compromise toward the >>>>>>>>> latter; after all, one big fat namespace is always unmanageable, >>>>>>>>> right? Well, there's ways to make that easy to manage. :) Let's call >>>>>>>>> it "optional, provided, explicit scoping", explicit because you don't >>>>>>>>> have to grok the contextual scope to understand a reference, optional >>>>>>>>> because you can ignore it, and provided because Velocity does the work >>>>>>>>> of choosing "prefixes" and creating/destroying the scopes (as any >>>>>>>>> implicit scoping system does). So everything is becoming globally >>>>>>>>> scoped, but it is now trivial to turn on automatic, explicit scopes or >>>>>>>>> namespaces that you can use when you don't want things to live in the >>>>>>>>> global scope. >>>>>>>>> >>>>>>>>> Here's an example... Do you use $velocityCount to get an index of >>>>>>>>> sorts inside of #foreach directives? Well, that's an example of mixed >>>>>>>>> implicit/explicit namespacing that gets messy when you nest >>>>>>>>> #foreach's, with no good way to get the parent's count and >>>>>>>>> unwieldiness when you want to add $velocityIndex, $velocityHasNext and >>>>>>>>> so on. Now, we automatically manage a $foreach var that not only has >>>>>>>>> a 'count' property, but an 'index', 'hasNext', 'parent', and so on >>>>>>>>> (see >>>>>>>>> http://velocity.apache.org/engine/devel/apidocs/org/apache/velocity/runtime/directive/ForeachScope.html). >>>>>>>>> It also, of course, accepts any property you want to set on it (like >>>>>>>>> any map). This makes templates instantly understandable, making >>>>>>>>> debugging much better. You always know exactly what you are referring >>>>>>>>> to, and so does anyone else reading the template. >>>>>>>>> >>>>>>>>> #foreach is the only 'content directive' that has its explicit scope >>>>>>>>> automatically turned on, but all content containing directives >>>>>>>>> (including custom body macros) can have their own explicit, >>>>>>>>> auto-managed scope, named after themselves. for example, you can flip >>>>>>>>> the macro scope on: >>>>>>>>> >>>>>>>>> macro.provide.scope.control = true >>>>>>>>> >>>>>>>>> and do: >>>>>>>>> >>>>>>>>> #macro( outer $arg ) >>>>>>>>> #set( $macro.arg = $arg ) >>>>>>>>> #inner( 'inner' ) >>>>>>>>> #end >>>>>>>>> #macro( inner $arg ) >>>>>>>>> #set( $macro.arg = $arg) >>>>>>>>> inner: $macro.arg >>>>>>>>> #if( $macro.parent )outer: $macro.parent.arg#end >>>>>>>>> #end >>>>>>>>> >>>>>>>>> #outer( 'outer' ) >>>>>>>>> #inner( 'just inner' ) >>>>>>>>> >>>>>>>>> and get >>>>>>>>> >>>>>>>>> inner: inner >>>>>>>>> outer: outer >>>>>>>>> inner: just inner >>>>>>>>> >>>>>>>>> Hope this helps... >>>>>>>>> >>>>>>>>> In any case, there was plenty of thought and discussion that went into >>>>>>>>> this change. Search http://velocity.markmail.org for 'scope' and you >>>>>>>>> should find more on this. >>>>>>>>> >>>>>>>>> On Mon, Apr 30, 2012 at 8:49 AM, Boris Partensky >>>>>>>>> <boris.parten...@gmail.com> wrote: >>>>>>>>>> Hello, while going through the upgrade I noticed an incompatible >>>>>>>>>> behavior during nested macro evaluation. Looks like in 1.7 (all >>>>>>>>>> default properties) child macro has access to variables set in parent >>>>>>>>>> macro scope (and those take precedence over globals), and 1.5 sees >>>>>>>>>> globals. In the following example, in 1.5 unit test the following >>>>>>>>>> template will evaluate to "globalvar", and in 1.7 - to >>>>>>>>>> "outermacroparam". Is this expected behavior? >>>>>>>>>> >>>>>>>>>> >>>>>>>>>> 1.5 test case >>>>>>>>>> >>>>>>>>>> >>>>>>>>>> public void testVelocityNestedMacroScope() throws Exception >>>>>>>>>> { >>>>>>>>>> VelocityEngine ve = new VelocityEngine(); >>>>>>>>>> >>>>>>>>>> ve.init(); >>>>>>>>>> >>>>>>>>>> String template = "#macro(outerMacro $arg1)"+ >>>>>>>>>> "#innerMacro('blah')"+ >>>>>>>>>> "#end"+ >>>>>>>>>> "#macro(innerMacro $arg2)$arg1#end"+ >>>>>>>>>> >>>>>>>>>> "#set($arg1='globalval')#outerMacro('outermacroparam')"; >>>>>>>>>> StringWriter eval = new StringWriter(); >>>>>>>>>> boolean b = ve.evaluate(new VelocityContext(), eval, "foo", >>>>>>>>>> template); >>>>>>>>>> assertEquals(eval.toString(), "globalval", eval.toString()); >>>>>>>>>> >>>>>>>>>> } >>>>>>>>>> >>>>>>>>>> 1.7 test case >>>>>>>>>> >>>>>>>>>> >>>>>>>>>> public void testVelocityNestedMacroScope() >>>>>>>>>> { >>>>>>>>>> String template = "#macro(outerMacro $arg1)"+ >>>>>>>>>> "#innerMacro('blah')"+ >>>>>>>>>> "#end"+ >>>>>>>>>> "#macro(innerMacro $arg2)$arg1#end"+ >>>>>>>>>> >>>>>>>>>> "#set($arg1='globalvar')#outerMacro('outermacroparam')"; >>>>>>>>>> String eval = evaluate(template); >>>>>>>>>> assertEquals(eval, "outermacroparam", eval); >>>>>>>>>> >>>>>>>>>> } >>>>>>>>>> >>>>>>>>>> --------------------------------------------------------------------- >>>>>>>>>> To unsubscribe, e-mail: user-unsubscr...@velocity.apache.org >>>>>>>>>> For additional commands, e-mail: user-h...@velocity.apache.org >>>>>>>>>> >>>>>>>>> >>>>>>>>> --------------------------------------------------------------------- >>>>>>>>> To unsubscribe, e-mail: user-unsubscr...@velocity.apache.org >>>>>>>>> For additional commands, e-mail: user-h...@velocity.apache.org >>>>>>>>> >>>>>>>> >>>>>>>> --------------------------------------------------------------------- >>>>>>>> To unsubscribe, e-mail: user-unsubscr...@velocity.apache.org >>>>>>>> For additional commands, e-mail: user-h...@velocity.apache.org >>>>>>>> >>>>>>> >>>>>>> --------------------------------------------------------------------- >>>>>>> To unsubscribe, e-mail: user-unsubscr...@velocity.apache.org >>>>>>> For additional commands, e-mail: user-h...@velocity.apache.org >>>>>>> >>>>>> >>>>>> --------------------------------------------------------------------- >>>>>> To unsubscribe, e-mail: user-unsubscr...@velocity.apache.org >>>>>> For additional commands, e-mail: user-h...@velocity.apache.org >>>>>> >>>>> >>>>> --------------------------------------------------------------------- >>>>> To unsubscribe, e-mail: user-unsubscr...@velocity.apache.org >>>>> For additional commands, e-mail: user-h...@velocity.apache.org >>>>> >>>> >>>> --------------------------------------------------------------------- >>>> To unsubscribe, e-mail: user-unsubscr...@velocity.apache.org >>>> For additional commands, e-mail: user-h...@velocity.apache.org >>>> >>> >>> --------------------------------------------------------------------- >>> To unsubscribe, e-mail: user-unsubscr...@velocity.apache.org >>> For additional commands, e-mail: user-h...@velocity.apache.org >>> >> >> --------------------------------------------------------------------- >> To unsubscribe, e-mail: user-unsubscr...@velocity.apache.org >> For additional commands, e-mail: user-h...@velocity.apache.org >> > > --------------------------------------------------------------------- > To unsubscribe, e-mail: user-unsubscr...@velocity.apache.org > For additional commands, e-mail: user-h...@velocity.apache.org > --------------------------------------------------------------------- To unsubscribe, e-mail: user-unsubscr...@velocity.apache.org For additional commands, e-mail: user-h...@velocity.apache.org