PGF における \pgf@marshal の慣用的な使用法

PGF における \pgf@marshal の慣用的な使用法

\pgf@marshalPGF パッケージ全体で、明らかに慣用的な使用法に遭遇しましたが、なぜそれが使用されるのか疑問に思います。

例えばpgflibraryshapes.gates.logic.US.code.tex:

{%
    \edef\pgf@marshal{%
        \noexpand\pgfpatharc{90}{-90}{\the\pgf@yc}%
    }%
    \pgf@marshal%
}

これはおそらく簡単なことだろうが、

\pgfpatharc{90}{-90}{\the\pgf@yc}

?

答え1

\pgfpatharcは使用しません(\pgf@yc少なくとも、すでに評価されてどこか別の場所に保存されるまでは使用しません)。

\pgfpatharc{90}{-90}{\pgf@yc}

(偶数なしで\the)、マニュアル自体に警告がある

注意:PGFはこれらのレジスタを使用してパス操作を実行します。効率上の理由から、パスコマンドは必ずしもこれらを保護しません。その結果、コード

\pgfpointadd{\pgfpoint{\pgf@xa}{\pgf@ya}}{\pgfpoint{\pgf@xb}{\pgf@yb}}

失敗する可能性があります: 内部では\pgfpointadd\pgf@xaおよび フレンド レジスタが変更される可能性があります。特に、 が評価される\pgf@xb前に が変更される可能性があります\pgfpoint{\pgf@xb}{\pgf@yb}。正しい対処法は、まず を使用してすべてを展開し、その後で値を処理することですが、これにより不必要なコストの高い操作が発生します。もちろん、 のソース コードを調べてどのレジスタが使用されているかを確認するだけ\edefで、これを回避できます。\pgfpointadd

(興味深いことに、与えられた例は実際には機能しますが、

\pgfpointadd{\pgfpoint{\pgf@xb}{\pgf@yb}}{\pgfpoint{\pgf@xa}{\pgf@ya}}

最初の点の座標は に格納され\pgf@xa\pgf@ya後で 2 番目の点の座標に追加されるためです。

の場合\pgfpatharc、が使用される#3前に が評価され、これはスコープ内でのみ発生するため、の後も同じ値になります。\pgf@yc\pgf@yc\pgfpatharc

つまり、回路ライブラリの開発者は の定義を調べて\pgfpatharc、意味がないと判断できたはずです。

しかし、他にも考慮すべき点があります。

  • \pgfpatharc回路ライブラリの作成時点では、コマンドの動作が異なっていた可能性があります。
  • コマンド\pgfpatharcは将来変更される可能性があります。
  • 回路ライブラリの作成者は、別の時点で競合に気づき、同様のマクロ呼び出しをすべて変更したため、二度とこのような問題に悩まされることはなくなりました。

答え2

TeX 実行モデルにあまり詳しくない人のための別の視点。


ウィクショナリー:

marshal (動詞)
4. 送信用にデータを収集する。
5. (コンピューティング、他動詞) オブジェクトを、後で同等のプロパティを持つオブジェクトに変換できるバイト シーケンスによって表されるマーシャリングされた状態にシリアル化すること。

コンピューティングのコンテキストでは通常、意味 5 が望まれますが、この場合は意味 4 の方が関連性が高いようです。ただし、これは「コードをトークン リストにシリアル化し、後でトークン リストをコードとして実行する」と理解することもできますが、TeX では、コードとトークン リストはほぼ同じものです。

要約:

  • デフォルトでは、TeX コマンドは「外側から内側へ」実行されます。つまり、「関数の引数」が「関数に渡される」前に「評価」される一般的なプログラム言語とは異なり、TeX では引数がそのままマクロに渡されます。

    • Python では、は受け取る前に と評価されるため、f(1+2)f(3)同一です。TeX では、は同一ではありません。1+23f\f{\numexpr 1+2\relax}\f{3}
  • この場合、もう一つの答え呼び出し元は、関数に渡す前に数値を早期に評価したいと考えています。

  • TeXにはトークンを操作するための非常に限られたメカニズムしかありません。あなたが見ているコードは次のようなものと同等です。

    eval(r"\pgfpatharc{90}{-90}{" + pgfyc + "}")
    

    Python 構文では、コードはトークン リストとして操作されて実行されます。

    代わりに、\expandafterコード内のあらゆる場所に を追加することになりますが、これは明らかに効率が悪くなります。( もあります\expanded{\unexpanded{...}}が、コードが作成された時点では存在していませんでした。)

  • この慣用句が使われている他の場所としては、例えばpgfplotsループ内でプロットを使用する方法\edef\temp{...}\temp

  • プレフィックスはpgf@、マクロ名が pgf パッケージ内部のものであることを示します。PGF/TikZ ソース コードを編集していない場合は、独自の名前を作成し、を再利用しないでください\pgf@marshal

関連情報