Close Velocity Pattern Macros

I have several Velocity macros:

#macro(Alpha) #set($p = 1) #@Beta() $p // 1 $bodyContent #end #end #macro(Beta $params) #set($p = 2) $p // 2 $bodyContent #end 

And I use them like this:

 #set($p = 0) #@Alpha(...) $p // 3 #end 

I believe it looks like this (ignore formatting): 2, 2, 2

But I would like to have the correct closing behavior, including more locally restricted names hiding the names of the parent areas. In particular, the use of $ p labeled '3' should refer to the value 0, '2' to the value 2, and '1' to the value 1.

Given the correct closing semantics, it will print: 2, 1, 0

Is there a way to get this, or a way to implement a custom directive / modification of the behavior of the #macro directive for this?

0
source share
1 answer

Velocity is a template engine, not the right programming language, so it's a little harder to understand how it works.

Macros are not functions, as in Java or C, which means that a macro call is not going to create a new segment on the stack for local variables; speed works with context, and most of the time there is only one global context.

However, there are two ways to solve local variables:

  • Here is the configuration parameter velocimacro.context.localscope , which prevents the change of global variables from macros; note that this option is outdated and will be removed in Velocity 2.0
  • You can use the $macro variable as a local container for private variables if you enable the macro.provide.scope.control configuration macro.provide.scope.control

However, there is another problem that would prevent your code from running correctly: Velocity macros work mostly as a default spread , which means that the body passed to the macro is not evaluated first and then passed to the macro; it will be dynamically evaluated when executing a nested macro. The code behaves like:

 #macro(Alpha) #set($macro.p = 1) -> $macro refers to Alpha $p -> $p will always be 0, since we're changing a local variable $macro.p -> 1 here $bodyContent -> Here $p is used, and 0 is printed #@Beta() $macro.p -> it is 1 now, but when this line will be actually evaluated, $macro will refer to Beta, so 2 will be printed $bodyContent -> It the content of the Beta macro, which triggers an infinite recursion; it not $p as above #end #end #macro(Beta) #set($macro.p = 2) -> $macro refers to Beta $macro.p -> 2 here $bodyContent -> the $bodyContent that was passed into the $bodyContent is evaluated now, so it causes a recursion #end #set($p = 0) #@Alpha() $p -> Global variable #end 
+5
source

Source: https://habr.com/ru/post/1440809/


All Articles