One more remark regarding the macro evaluation strategy, especially
after reading the article you mentionned below.
It states that the new behaviour is the following:
#macro(callBySharing $x $map)
#set($x = 'a')
$map.put('x', 'a')
#end
#set($y = 'y')
#set($map = {})
#callBySharing($y $map)
$y -> 'y' (but is 'a' in 1.6.2, 1.6.0 and before)
$map.x -> 'a'
But this is not completely true. The following example contradicts that
statement:
#macro(callBySharing $x $map)
#set($x = 'a')
$map.put('x', 'a')
#end
*#set($x = 'x')*
#set($map = {})
#callBySharing($y $map)
*$x -> 'a' (and is also 'a' in 1.6.2, 1.6.0 and before)*
$map.x -> 'a'
Isn't this even more counter-intuitive? Is this expected or is it a
known bug?
Cheers,
Guillaume
Le 20/10/2011 14:49, Sergiu Dumitriu a écrit :
On 10/20/2011 08:41 AM, Guillaume Polet wrote:
Hi List,
it's been a while since I wrote here (at least a few years), mainly
because I had not too much trouble resolving my issues myself but this
time I am kind of stuck.
We recently upgraded from Velocity 1.6.2 to velocity 1.7 and we
encountered a lot of issues. While I managed to fix most of them, there
is an important one that I can't get passed.
Simplifying my code, here is a little snippet that used to work:
#macro(foo $bar)
#set($bar = 100)
#end
#set($xyz = 0)
Before: $xyz
#foo($xyz)
After: $xyz
Basically, we pass a variable to a macro, and setting the value of the
variable in the macro impacted the passed argument, ie, the output we
used to have in 1.6.2 was:
Before: 0
After: 100
Now, in velocity 1.7, I get the following:
Before: 0
After: 0
This is of course a really strong change of behaviour but ok I guess
there might be some good reason for that (although I think it kind of
contradicts what the doc says about velcoity macro arguments since it
says that the passed argument is re-evaluated each time it occurs in the
VM, in my opinion, I feel that $bar should resolve to $xyz, and
therefore the #set would set the value of $xyz. The whole point of doing
that is to be able to return a value (or even several values) from a
macro).
Now, the weirdest thing, I believe is, if you change the name of the
passed argument to $bar:
#macro(foo $bar)
#set($bar = 100)
#end
#set($bar= 0)
Before: $bar
#foo($bar)
After: $bar
Then I get what I used to have, ie:
Before: 0
After: 100
I feel like this is really mixing things up. Either the value can
propagate from the macro to the calling-level, either it should be
prevented. But have a mix of both of them is really not predictable nor
robust. If by any chance, I happen to call my argument the same way it
is called in the macro, the behaviour of the template is completely
changed. I would assume that the name of a variable should not matter on
both sides. I should be able to rename $bar to $bar123 without noticing
any change and the same goes for $xyz which could be either $xyz or $bar
without modifying the outcome. Or is this just me?
Personnally, I am in favour of the first behaviour.
Now, my question would be, how can I achieve the behaviour observed in
1.6.2 with velocity 1.7, or what technique can I use to return values
from a velocity macro?
If you wonder why I am trying to that instead of moving my code to Java
classes, the reason is that I heavily rely on templates to generate all
kinds of stuff (full web-application, Latex documents, DocX documents,
etc...) but I also allow the user of my application to modify those
templates at runtime without needing to know anything about classes,
Java code, etc... I can get somebody started on VTL in 5 minutes while
it would take me days to get him started with Java.
Thanks very much in advance,
See http://wiki.apache.org/velocity/MacroEvaluationStrategy and
http://www.xwiki.org/xwiki/bin/ReleaseNotes/ReleaseNotesXWikiEnterprise30#HMacroevaluationstrategy