
\pgf@marshal
Ich 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 \pgfpatharc
verwendet 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 \the
gerade), 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
\pgfpointadd
die\pgf@xa
und befreundeten Register geändert werden. Insbesondere kann es passieren, dass\pgf@xb
geändert wird, bevor\pgfpoint{\pgf@xb}{\pgf@yb}
ausgewertet wird. Das Richtige wäre, zuerst alles mit zu erweitern\edef
und 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,\pgfpointadd
um 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@xa
und \pgf@ya
später zu denen des zweiten Punkts addiert werden.)
Im Fall von wird get ausgewertet, bevor \pgfpatharc
es 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 \pgfpatharc
und feststellen können, dass es keinen Sinn hat.
Doch es gibt noch weitere Punkte zu beachten:
\pgfpatharc
Zum Zeitpunkt des Schreibens der Schaltungsbibliothek funktionierte der Befehl möglicherweise anders.- Der
\pgfpatharc
Befehl 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)
undf(3)
identisch, da vor dem Empfang1+2
zu ausgewertet wird . In TeX sind und nicht identisch.3
f
\f{\numexpr 1+2\relax}
\f{3}
- in Python sind
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
pgfplots
Plot 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
.