关闭Velocity模板宏

gza*_*zak 1 templates closures velocity

我有一些像这样的Velocity宏:

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

#macro(Beta $params)
  #set($p = 2)
  $p               // 2
  $bodyContent
#end
Run Code Online (Sandbox Code Playgroud)

而我正在使用它们:

#set($p = 0)
#@Alpha(...)
  $p               // 3
#end
Run Code Online (Sandbox Code Playgroud)

我相信这样渲染(忽略格式化):2,2,2

但我希望有适当的关闭行为,包括隐藏父范围名称的更多本地范围名称.特别是,标记为'3'的$ p的使用应该是值0,'2'表示值2,'1'表示值1.

给定正确的闭包语义,它将打印:2,1,0

有没有办法得到这个,或者一种方法来实现自定义指令/修改#macro指令行为来实现这一目标?

Ser*_*riu 5

Velocity是一个模板引擎,而不是一种适当的编程语言,所以要掌握它是如何工作的有点困难.

宏不是Java或C中的函数,这意味着调用宏不会在堆栈上为局部变量创建新段; velocity与上下文一起工作,大多数时候只有一个全局上下文.

仍然有两种处理局部变量的方法:

  1. 有一个velocimacro.context.localscope配置参数可以防止在宏中更改全局变量; 请注意,此设置已弃用,将在Velocity 2.0中删除
  2. $macro如果启用macro.provide.scope.control配置参数,则可以将该变量用作私有变量的本地容器

仍然存在另一个会阻止代码正常运行的问题:Velocity宏主要用作逐个宏调用的扩展,这意味着传递给宏的主体不会先被评估,然后传递给宏; 执行嵌套宏时将动态评估它.代码表现为:

#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's the content of the Beta macro, which triggers an infinite recursion; it's 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
Run Code Online (Sandbox Code Playgroud)