5

基本的に次のようなマクロがあります。

#macro( surround $x )
  surround:$x
    $bodyContent
  /surround:$x
#end

呼び出し#@surround("A")bunch o' stuff#endにより、期待どおりに「surround:A bundle o' stuff /surround:A」が生成されます。呼び出しにより、 Surround #@surround("A")#@surround("B")more stuff#end#end:A Surround:B more stuff /surround:B /surround:A が生成されます。これはまさに私が望むものです。

でも今は別のマクロで上向きにビルドしたい

#macro( annotated-surround $x $y )
  #@surround( $x )
    annotate:$y
    $bodyContent
  #end
#end

意図した展開#annotated-surround( "C" "note" ) stuff #endは Surround:C annotate:note stuff /surround:C です

...しかし、これは機能しません。注釈付きサラウンド ボディ コンテンツの恐るべき半無限拡張を取得します。

Closure in Velocity template macros で回答を読みましたが、やりたいことが可能かどうかまだよくわかりません。

#surroundと の定義内で勝手にトリッキーなことをして#annotated-surroundも構わないと思っていますが、それらのマクロのユーザーに複雑さを感じてほしくないのです。全体のアイデアは、彼らの生活を簡素化することです。

私があなたの耳を持っている限り:設定macro.provide.scope.control=trueは「マクロのローカル名前空間」に想定されています。これは何を意味するのでしょうか?指定された名前空間はデフォルトのコンテキストから独立していますが、すべてのマクロのすべての呼び出し間で共有される単一のそのようなスペースがありますか? それとも、再帰的であっても、マクロ呼び出しごとに個別のコンテキストが提供されますか? という理由で後者でなければなり$macro.parentませんよね?

そして、さらに別の質問です。次のマクロを検討してください。

#macro( recursive $x )
  #if($x == 0)
    zero
  #else
    $x before . . . 
    #set($xMinusOne = $x - 1)
    #recursive($xMinusOne)
    . . . $x after
  #end
#end

#recursive( 4 )収量:

4 前に。. . 3 前に。. . 2 前に。. . 1 前に。. . ゼロ 。. . 0 後。. . 0 後。. . 0 後。. . 4後

これで、「0」のすべての出現を理解できました。グローバルな $x は 1 つしかないため、再帰呼び出しでそれに割り当てると、それが破壊され、復元されません。しかし、その最後の「4」は一体どこから来たのでしょうか? さらに言えば、私の最初の「サラウンド」マクロが任意の深さまで機能するのはどうしてですか。最後の $x が内部呼び出しで破壊されないのはなぜですか?

長くなって申し訳ありませんが、この件に関して明確な文書を見つけることができませんでした。

4

2 に答える 2

0

最も簡単なものから始めて、macro.provide.scope.control=true は、すべてのマクロ呼び出しに対して個別の $macro スコープ オブジェクトを確実に作成します。そうしないと、お気づきのように、 $macro.parent はナンセンスになります。「スコープ コントロール」の要点は、問題の VTL ブロックのタイプに明示的な名前空間を提供することです。Surround.provide.scope.control=true を実行して、#@surround bodyContent 内に $surround スコープを自動的に作成することもできます。

最初の質問で、何が起こっているのか少し混乱しています。#@annotate-surround への呼び出しと #@surround へのネストされた呼び出しの両方で、$bodyContent 参照が利用可能になります。「間違った」$bodyContent が使用されているというのは正しいのでしょうか。$bodyContent 参照は、最も近いブロック マクロ呼び出しに属している必要があります。内側のマクロ内で外側のマクロの $bodyContent を参照するには、おそらく #set( $macro.bodyContent = $bodyContent ) が必要であり、内側では $macro.parent.bodyContent を介して使用します。

#recursive の奇妙さについては、私はすぐにはわからないので、今すぐ他の作業に取り掛かる必要があります。また、現在のマシンで Velocity をチェックアウトしていないことも役に立ちません。そのため、すぐに試してみることができません。

于 2012-10-19T22:10:30.470 に答える