You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@velocity.apache.org by Christoph Reck <Ch...@dlr.de> on 2002/03/26 09:18:09 UTC

Re: macro arguments may change implicitely - why not store arguments in local context ?

Hi, 

this is why I've been proposing to implement a 
  #local( $var1 $var2 ... $varN )
    ...
  #end
directive to allow using $var1-N locally without touching whatever these held
externaly. This would greatly enhance the usability of a predefined macro
library. Also it would help creating independent template fragements that can
be #parsed into other templates.

Creating such a #local directive is an easy task: just take the #foreach 
directive source and modify it to do what you want - either by saving the
var1-N the original context containsKey(varX) or by chaining a new context
onto the current one with the var1-N predefined (e.g. to Boolean.FALSE) on 
it.

I'm currently working on another Swing-based project and have no chance to
write and test this, but anyone could take up this chore...

:) Christoph

Claude Brisson wrote:
> 
> I'd like to discuss a strange behaviour (already mentionned sometimes, but without any concluding point, imho), and to make a
> proposal.
> 
> When velocimacro.context.localscope is false, a macro may implicitely change the actual value of its arguments by changing some
> external variable implied in their calculation.
> 
> This is due to the fact that each time a non-constant argument is evaluated in a macro, it is re-evaluated with the global context
> that may have been changed by the same macro.
> 
> For instance, as shown in example 1, if a #foreach or a #set directive inside a macro uses a reference name similar to the name of a
> reference passsed to the macro, then the actual value of the parameters may also change in the same time.
> 
> ---------------------
> 
> ## Example 1 :
> 
> ## outputs "1 ! a b c" instead of expected "1 1 1 1 1"
> 
> #macro (test $arg)
>  $arg ## -> 1
>  #set($i = '!')
>  $arg ## -> !
>  #foreach ($i in ['a','b','c'])
>   $arg ## -> a b c
>  #end
> #end
> 
> #set($i = 1)
> #test($i) ## outputs "1 ! a b c" instead of expected "1 1 1 1 1"
> 
> ---------------------
> 
> This may be seen as a small side effect, but it can lead to very ankward behaviours in some situations... especially when dealing
> with macro recursions.
> 
> ---------------------
> 
> ## Example 2 : (partial)
> 
> #macro (disp_node $node)
>  #foreach ($child in $node.children())
> 
>   $child.name is a child of $node.name
>   ##                        ^^^^^^^^^^      (I hate proportional fonts)
>   ## "$node.name" evaluate to (external) "$child.name", which equals (internal) "$child.name"
>   ## so for a basic tree (grandparent-parent-grandson) we get the output "grandson is a child of grandson"
> 
>   #disp_node($child)
>  #end
> #end
> 
> ---------------------
> 
> This recursion problem should also be solved if #foreach directives avoided to store their working variables in the global context,
> but it's another point.
> 
> I finally made it out for my personal stuff, by the mean of two or three dreadful workarounds, but here is my point :
> 
>       Why couldn't macro directives only evaluate once their arguments at the moment they are called and save them in their local
> context ?
> 
> This sounds too simple... do I miss something ?
> 
> As shown in example 3, only vicious minds (like mine here, for a didactic purpose) may try to exploit constructively this behaviour.
> Otherwise, it's rather strange (and time consuming) to re-evaluate arguments each time.
> 
> ---------------------
> 
> ## Example 3 : outputs "hello folks"
> 
> #macro (print_twice $value)
>  $value $value
> #end
> 
> #set ($myarray = ["hello","folks"])
> 
> #print_twice($myarray.remove(0))
> 
> ---------------------
> 
> Depending on the followup, I'd be glad to try to contribute attenant patches.
> 
> Thanx for reading up to that point.
> And last but not least, thanx a lot to the support team.
> 
> Sincerely,
> 
> CloD
> 
> --
> To unsubscribe, e-mail:   <ma...@jakarta.apache.org>
> For additional commands, e-mail: <ma...@jakarta.apache.org>

-- 
:) Christoph Reck

--
To unsubscribe, e-mail:   <ma...@jakarta.apache.org>
For additional commands, e-mail: <ma...@jakarta.apache.org>