Idiomatische Verwendung von \pgf@marshal in PGF

Idiomatische Verwendung von \pgf@marshal in PGF

\pgf@marshalIch bin im gesamten PGF-Paket auf eine anscheinend idiomatische Verwendung von gestoßen und frage mich, warum es verwendet wird.

Zum Beispiel von pgflibraryshapes.gates.logic.US.code.tex:

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

Das ist wahrscheinlich einfach, aber warum nicht einfach

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

?

Antwort1

While \pgfpatharcverwendet nicht \pgf@yc(zumindest nicht, bis es bereits ausgewertet und woanders gespeichert wurde) und es wäre sicher gewesen,

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

(ohne das \thegerade), dieHandbuch selbst warnt

Aufmerksamkeit:PGF verwendet diese Register, um Pfadoperationen durchzuführen. Aus Effizienzgründen schützen Pfadbefehle sie nicht immer. Als Konsequenz davon ist der Code

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

kann fehlschlagen: Innerhalb von können \pgfpointadddie \pgf@xaund befreundeten Register geändert werden. Insbesondere kann es passieren, dass \pgf@xbgeändert wird, bevor \pgfpoint{\pgf@xb}{\pgf@yb}ausgewertet wird. Das Richtige wäre, zuerst alles mit zu erweitern \edefund die Werte anschließend zu verarbeiten, was zu unnötig teuren Operationen führt. Natürlich kann man dies vermeiden, indem man einfach in den Quellcode von schaut, \pgfpointaddum zu sehen, welche Register verwendet werden.

(Interessanterweise würde das gegebene Beispiel tatsächlich funktionieren, aber nicht

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

weil die Koordinaten des ersten Punkts gespeichert \pgf@xaund \pgf@yaspäter zu denen des zweiten Punkts addiert werden.)

Im Fall von wird get ausgewertet, bevor \pgfpatharces verwendet wird, und dies geschieht nur innerhalb des Bereichs, hat also nach immer noch den gleichen Wert .#3\pgf@yc\pgf@yc\pgfpatharc

Also, ja, der Entwickler der Schaltungsbibliothek hätte einen Blick auf die Definition werfen \pgfpatharcund feststellen können, dass es keinen Sinn hat.

Doch es gibt noch weitere Punkte zu beachten:

  • \pgfpatharcZum Zeitpunkt des Schreibens der Schaltungsbibliothek funktionierte der Befehl möglicherweise anders.
  • Der \pgfpatharcBefehl kann sich in Zukunft ändern.
  • Dem Autor der Schaltungsbibliothek ist an einer anderen Stelle ein Konflikt aufgefallen und er hat alle ähnlichen Makroaufrufe so geändert, dass er nie wieder mit derartigen Problemen zu kämpfen hat.

Antwort2

Eine andere Perspektive für diejenigen, die mit dem TeX-Ausführungsmodell nicht sehr vertraut sind.


Wiktionary:

marshallen (Verb)
4. Daten zur Übertragung sammeln.
5. (Computertechnik, transitiv) Ein Objekt in einen marshallten Zustand serialisieren, der durch eine Bytefolge dargestellt wird, die später wieder in ein Objekt mit gleichwertigen Eigenschaften umgewandelt werden kann.

Während im Computerkontext normalerweise die Bedeutung 5 erwünscht ist, scheint in diesem Fall die Bedeutung 4 relevanter zu sein. Es könnte aber auch als „serialisieren Sie den Code in eine Tokenliste, führen Sie die Tokenliste später als Code aus“ verstanden werden – aber in TeX sind Code und Tokenliste meistens dasselbe.

kurz und knapp:

  • Standardmäßig werden TeX-Befehle „von außen nach innen“ ausgeführt. Das heißt, im Gegensatz zu typischen Programmiersprachen, in denen „Funktionsargumente“ „ausgewertet“ werden, bevor sie „an die Funktion übergeben“ werden, wird in TeX das Argument wörtlich an das Makro übergeben.

    • in Python sind f(1+2)und f(3)identisch, da vor dem Empfang 1+2zu ausgewertet wird . In TeX sind und nicht identisch.3f\f{\numexpr 1+2\relax}\f{3}
  • In diesem Fall, wie indie andere Antwort, der Anrufer möchte die Nummer frühzeitig auswerten, bevor er sie an die Funktion übergibt.

  • TeX verfügt über eine sehr begrenzte Anzahl von Mechanismen zur Manipulation von Token. Der Code, den Sie sehen, entspricht etwa

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

    in der Python-Syntax – der Code wird als Token-Liste bearbeitet und dann ausgeführt.

    Die Alternative wäre, \expandafterüberall im Code hinzuzufügen, was definitiv weniger effizient ist. (Es gibt auch \expanded{\unexpanded{...}}, aber das existierte zum Zeitpunkt des Schreibens des Codes noch nicht.)

  • Andere Stellen, an denen diese Redewendung verwendet wird, sind zum BeispielSo verwenden Sie pgfplotsPlot in einer Schleifemit \edef\temp{...}\temp.

  • Das Präfix pgf@gibt an, dass der Makroname intern im PGF-Paket ist. Wenn Sie den PGF/TikZ-Quellcode nicht bearbeiten, sollten Sie Ihren eigenen Namen erstellen und ihn nicht wiederverwenden \pgf@marshal.

verwandte Informationen