You are viewing a plain text version of this content. The canonical link for it is here.
Posted to user@velocity.apache.org by Steve O'Hara <so...@pivotal-solutions.co.uk> on 2010/01/14 11:18:18 UTC

Evaluation of macro arguments

I've just come across a little gotcha that has taken a few hours to
track down which might help other people.

An example;

#macro(myMacro $FieldName)
    #foreach ($Name in $FieldList)
        #if ($FieldName=="empty")
            #set ($tmp=$FieldsFound.put($FieldName,$velocityCount)
        #end
    #end
#end

#foreach ($X in $MyFields)
    #myMacro("Field$velocityCount")
#end

All looks OK doesn't it, but........

The problem is one of when arguments are evaluated or in fact to be more
precise, are not evaluated at all.
Once you bear that in mind you can see the logical problem above - the
use of $velocityCount (or indeed any variable) in the argument list of
myMacro i.e. 

#myMacro("Field$velocityCount")

This sort of usage is dangerous because in effect, what is happening is
that the macro argument literal is being placed within the macro body
without being evaluated first.
So, the body of the macro becomes this;

    #foreach ($Name in $FieldList)
        #if ("Field$velocityCount"=="empty")
            #set
($tmp=$FieldsFound.put("Field$velocityCount",$velocityCount)
        #end
    #end

Not what you intended at all and depending on the names of your
variables, could cause all kinds of mayhem with values coming into scope
that you hadn't intended.

The workaround is to set a variable before the call to the macro and
send that instead e.g.

#foreach ($X in $MyFields)
    #set ($tmp="Field$velocityCount")
    #myMacro($tmp)
#end

Nathan: I'm happy to add to JIRA if you think it's a bug - just thought
I'd share it with the community, might save some heartache for someone.

Steve

---------------------------------------------------------------------
To unsubscribe, e-mail: user-unsubscribe@velocity.apache.org
For additional commands, e-mail: user-help@velocity.apache.org


Re: Evaluation of macro arguments

Posted by Nathan Bubna <nb...@gmail.com>.
Yeah, go ahead and add it to JIRA.  It's unexpected enough that we
should consider options to improve this.

On Thu, Jan 14, 2010 at 2:18 AM, Steve O'Hara
<so...@pivotal-solutions.co.uk> wrote:
> I've just come across a little gotcha that has taken a few hours to
> track down which might help other people.
>
> An example;
>
> #macro(myMacro $FieldName)
>    #foreach ($Name in $FieldList)
>        #if ($FieldName=="empty")
>            #set ($tmp=$FieldsFound.put($FieldName,$velocityCount)
>        #end
>    #end
> #end
>
> #foreach ($X in $MyFields)
>    #myMacro("Field$velocityCount")
> #end
>
> All looks OK doesn't it, but........
>
> The problem is one of when arguments are evaluated or in fact to be more
> precise, are not evaluated at all.
> Once you bear that in mind you can see the logical problem above - the
> use of $velocityCount (or indeed any variable) in the argument list of
> myMacro i.e.
>
> #myMacro("Field$velocityCount")
>
> This sort of usage is dangerous because in effect, what is happening is
> that the macro argument literal is being placed within the macro body
> without being evaluated first.
> So, the body of the macro becomes this;
>
>    #foreach ($Name in $FieldList)
>        #if ("Field$velocityCount"=="empty")
>            #set
> ($tmp=$FieldsFound.put("Field$velocityCount",$velocityCount)
>        #end
>    #end
>
> Not what you intended at all and depending on the names of your
> variables, could cause all kinds of mayhem with values coming into scope
> that you hadn't intended.
>
> The workaround is to set a variable before the call to the macro and
> send that instead e.g.
>
> #foreach ($X in $MyFields)
>    #set ($tmp="Field$velocityCount")
>    #myMacro($tmp)
> #end
>
> Nathan: I'm happy to add to JIRA if you think it's a bug - just thought
> I'd share it with the community, might save some heartache for someone.
>
> Steve
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: user-unsubscribe@velocity.apache.org
> For additional commands, e-mail: user-help@velocity.apache.org
>
>

---------------------------------------------------------------------
To unsubscribe, e-mail: user-unsubscribe@velocity.apache.org
For additional commands, e-mail: user-help@velocity.apache.org