Passing variables into Velocity macros by value

Hi,

Does anyone know how to pass a variable into a macro by value? Is there some technique or trick of syntax that anyone has found? Because at the moment I cannot find a way to keep track of iterations of a self-calling macro, because any $iteration variable I define, and pass between iterations, becomes a reference to the same number.

Thanks,

Andrew.

Yes, I would be curious as to a solution / trick / technique for this as well. I have noticed that the scope of $velocityCount is correct, but all the other variables do get over-written outside what I consider their correct scope.

Fortunately for me, the one place where I should use a recursive function, I was able to break it out to 3 almost identical macros with just a change in variable names (var1, var2, etc). Ideally of course it would be nice for it to just be one function.

Also in this case, I created a separate macro with parameters that does the “heavy lifting” so the three macros just pass in variables to the other macro and get an appropriate response back. Not ideal, but it works.

I think I have found a kludge to get what I want. You have to increment the variable inside the brackets of the call to the macro, rather than with a #set() instruction on the previous line. This forces it to pass by value. But you cannot just add a +1, because basic maths doesn’t seem to be allowed inside a macro call. So you have to use a method of the $tools object. Here is an example:


#macro(testing123 $var)##
<ul>##
	<li>The value of var is $var</li>##
	#if($var < 10)##
		#testing123($tools.math.add($var,1))##
	#end##
	<li>The value of var is $var</li>##
</ul>##
#end##

When this macro is called by adding, for example, #testing123(1) to a template, the following is displayed:

  • The value of var is 1
    • The value of var is 2
      • The value of var is 3
        • The value of var is 4
          • The value of var is 5
            • The value of var is 6
              • The value of var is 7
                • The value of var is 8
                  • The value of var is 9
                    • The value of var is 10
                    • The value of var is 10
                  • The value of var is 9
                • The value of var is 8
              • The value of var is 7
            • The value of var is 6
          • The value of var is 5
        • The value of var is 4
      • The value of var is 3
    • The value of var is 2
  • The value of var is 1

Which was what I, at least, wanted. Without using this method, both the following versions of the macro display “10” for the value of the variable in the second half of the output:


#macro(testing123 $var)##
<ul>##
	<li>The value of var is $var</li>##
	#if($var < 10)##
		#set($var = $var+1)##
		#testing123($var)##
	#end##
	<li>The value of var is $var</li>##
</ul>
#end


#macro(testing123 $var)##
<ul>##
	<li>The value of var is $var</li>##
	#if($var < 10)##
		#set($var2 = $var+1)##
		#testing123($var2)##
	#end##
	<li>The value of var is $var</li>##
</ul>
#end

Andrew.

Thanks,
This is good to know…Now i might be able to rework my macros to be more efficient…

I have an update to this. Passing in an iterator variable using $tools.math.add($var,1) in the maco call does not pass by value. It is still passing a reference to that “add” method call of the $tools.math object. It works only because the 1 in the second argument to the method is constant. The following example explains this better than I can in words:

#macro(TestMacro $param1)
	$param1
	#set($bar = 2)
	$param1
	#set($bar = 3)
	$param1
#end

#set($foo = 1)
#set($bar = 1)
#TestMacro($tools.math.add($foo,$bar))

…you’d think the output would be…

2 2 2

…but it actually outputs…

2 3 4

…because every time it evaluates the $param1 parameter it calls the add method of the $tools.math object, which uses the current value of $foo and $bar.

Andrew.