Beim Arbeiten mit benutzerdefinierten Hutglyphen mit der ersten Version vondiese Lösung, pdflatex
das Kompilieren eines Dokuments dauerte sehr lange. In der verlinkten Antwort wird darauf hingewiesen, dass es sich um eine langsamere Lösung handelt, aber das war zunächst ziemlich langsam, was aber nicht weiter schlimm war. Dann wurde es gerade noch erträglich langsam, nachdem ich zwei gestapelte Hüte verwendet hatte. Und nachdem ich nachgeforscht und drei Hüte gestapelt hatte, wurde es ewig langsam.
Hier ist ein kurzer Grund:
\documentclass[12pt, a4paper]{article}
\usepackage{scalerel}
\begin{document}
\ensuremath{
\ThisStyle{
\SavedStyle\ThisStyle{
\SavedStyle\ThisStyle{
\SavedStyle\ThisStyle{
\SavedStyle\ThisStyle{
\SavedStyle\ThisStyle{
\SavedStyle\ThisStyle{
\SavedStyle\ThisStyle{
\SavedStyle . }}}}}}}
}}
\end{document}
pdflatex
Mit oder dauert das 15 Sekunden latex
. Wenn wir eine Verschachtelungsebene entfernen, sind es nur noch 2 Sekunden. Wenn wir eine Ebene mehr als im Beispiel hinzufügen, kommen wir auf 269 Sekunden.
Offensichtlich passiert hier etwas Exponentielles.scalerel.sty, der Code für \SavedStyle
und \ThisStyle
lautet wie folgt:
\def\SavedStyle{\csname @mstyle\m@switch\endcsname}
\newcommand\ThisStyle[1]{%
\ifmmode%
\def\@mmode{T}\mathchoice%
{\edef\m@switch{D}\LMex=1ex\relax\LMpt=1pt\relax#1}%
{\edef\m@switch{T}\LMex=1ex\relax\LMpt=1pt\relax#1}%
{\edef\m@switch{S}\LMex=\scriptstyleScaleFactor ex\relax%
\LMpt=\scriptstyleScaleFactor pt\relax#1}%
{\edef\m@switch{s}\LMex=\scriptscriptstyleScaleFactor ex\relax%
\LMpt=\scriptscriptstyleScaleFactor pt\relax#1}%
\else%
\def\@mmode{F}%
\edef\m@switch{T}\LMex=1ex\relax\LMpt=1pt\relax#1%
\fi%
}
Ich vermute, dass das Argument \ThisStyle
auf jeder Ebene viermal erweitert wird. Mit anderen Worten: \mathchoice
es ist nicht faul.
Gibt es eine Möglichkeit, das #1
Äußere dieser \mathchoice
Argumente zu entfernen und trotzdem das gleiche Verhalten beizubehalten? Bleiben diese \m@switch
und \LMex
Definitionen über das nächste " " hinaus bestehen }
?
Wenn nicht, gibt es einen anderen Ansatz, um das Äquivalent zu erreichen \ThisStyle
? \SavedStyle
Mir fällt nichts ein, was in linearer Zeit in Bezug auf die Verschachtelungstiefe funktionieren würde und bei Vorhandensein von Reentrancy immer noch korrekt funktionieren würde.
Antwort1
Kurze Antwort: Nein – es gibt keine Möglichkeit, dies in allen Situationen oder in einem LaTeX-Durchgang korrekt zu tun.
Nach viel Lernen und Experimentieren scheint es, dass der einzige Weg, dies zu umgehen, so etwas ist wieManuels Antwort und Kommentar hier. Es gibt kein \whatIsTheMathStyleHere
(es sei denn, wir sind auf LuaTeX). Der\mathchoice
command ist ein TeX-Grundelement.Die Wahl der vier Optionen erfolgtspätUm zu verstehen, was "spät" bedeutet, müssen wir uns bewusst machen, dass TeXeinige Verdauungsphasen: Auge, Mund,Speiseröhre, Magen, von denen jeder das logische Dokument in eine Form umwandelt, die dem endgültigen visuellen Dokument näher kommt, wobei eine Teilmenge der semantisch bedeutsamen Token durchgearbeitet wird.Manchmal geht es zum vorherigen Stadium zurück.(Aber rechtfertigt die fast zu gute, um wahr zu sein, schriftstellerische Intelligenz, die wir mittlerweile erwarten, nicht ein gewisses Maß an Komplexität?) Also, das Zeug rund um\mathchoice
Undinnerhalb seiner Argumente wird makroerweitert, bevor \mathchoice
es selbst angewendet wird. Tatsächlich werden, soweit ich das beurteilen kann, nicht nur Erweiterungen, sondern auch andere TeX-Befehle wie \ifx
vor verarbeitet \mathchoice
, sodass es innerhalb jeder Verarbeitungsphase mehrere geschichtete Unterphasen geben könnte?
Manuels Alternative, genannt \mathcase
, verwendet einen cleveren Trick, bei dem ein nanoskaliger Raum eingefügt wird, dessen Größe vom mathematischen Stil abhängt. Anschließend wird die Größe des Raums überprüft und der Stil bestimmt. Wie kann das funktionieren, wenn der endgültige mathematische Stil überall erst bestimmt werden soll, nachdem das Dokument eine vollständig aufgelöste Struktur hat? Dies geschieht mithilfe des zref-savepos
Pakets. In der Dokumentation für zref
findet sich ein Hinweis:
Die Seitenposition ist nicht sofort bekannt. Zuerst muss die Seite von der asynchronen Ausgaberoutine von TEX erstellt werden. Der Zeitpunkt, zu dem die Position bekannt ist, ist daher der Zeitpunkt der Seitenausgabe. Daher ist ein Referenzsystem nützlich, bei dem die Informationen im ersten Durchlauf aufgezeichnet und für den zweiten Durchlauf verfügbar gemacht werden.
Mit anderen Worten: Der richtige Mathematikstil wird bestimmt beiversenden, ab diesem Zeitpunkt kann es in keiner \if
oder anderen Entscheidungsstrukturen mehr verwendet werden, wird aber in der AUX-Datei gespeichert (wie Sie sehen können, wenn Sie die AUX-Datei für das folgende Beispiel untersuchen) und wird beim zweiten Durchgang verfügbar.
Leider führt dies zu folgendem Problem bei kaskadierenden mathematischen Stilen, die sich in einer verschachtelten Reihe von \mathcase
s ausbreiten: Wenn die Verschachtelung N-Ebenen tief ist, ist die Stabilität des Dokuments erst garantiert, wenn es N-mal kompiliert wurde. Beispiel:
(Das ist vonManuels Antwort, wo ich gerade den Dokumenttext geändert habe.)
\documentclass{scrartcl}
\usepackage{mathtools}
\usepackage{zref-savepos}
\newcount\mmstynum
\newcount\tmpnum
\protected\def\getmsty
{\global\advance\mmstynum1 %
\expandafter\getstyA\expandafter{\number\mmstynum}}
\protected\def\getstyA#1%
{\zsaveposx{mmsty-#1-a}%
\mathchoice{\kern4sp}{\kern3sp}{\kern2sp}{\kern1sp}%
\zsaveposx{mmsty-#1-b}
\tmpnum=\numexpr
\zposx{mmsty-#1-b} - \zposx{mmsty-#1-a}
\relax
\ifcase\tmpnum\or\kern-1sp \or\kern-2sp \or\kern-3sp \or\kern-4sp \fi}
\protected\def\mstycase
{\ifcase\tmpnum\expandafter\gobblefour\or\expandafter\usefourth\or
\expandafter\usethird\or\expandafter\usesecond\or
\expandafter\usefirst\else\expandafter\gobblefour\fi}
\protected\def\mathcase{\getmsty\mstycase}
\long\def\gobblefour#1#2#3#4{}
\long\def\usefourth#1#2#3#4{#4}
\long\def\usethird#1#2#3#4{#3}
\long\def\usesecond#1#2#3#4{#2}
\long\def\usefirst#1#2#3#4{#1}
\def\tmpa{If this prints it means it doesn't work}
\newcommand*\foo
{\mathcase % compare with \mathchoice
{\def\tmpa{displaystyle}}
{\def\tmpa{textstyle}}
{\def\tmpa{scriptstyle}}
{\def\tmpa{scriptscriptstyle}}
\text\tmpa}
\let\savedstyle\displaystyle
\def\thisstyle#1{\begingroup\mathcase{\let\savedstyle\displaystyle}{\let\savedstyle\textstyle}{\let\savedstyle\scriptstyle}{\let\savedstyle\scriptscriptstyle}#1\endgroup}
\begin{document}
\[
\sum \scriptstyle \sum \thisstyle{%
\fbox{\( \sum \savedstyle \sum \thisstyle{%
\fbox{\( \sum \savedstyle \sum \thisstyle{%
\fbox{\( \sum \savedstyle \sum \)}%
}\)}%
}\)}%
}
\]
\end{document}
Wenn wir uns das PDF während der Kompilierung im TeXworks-Viewer ansehen, sehen wir:
Nach dem ersten Durchgang:
Nach dem zweiten Durchgang:
Nach dem dritten Durchgang:
Nach dem vierten Durchgang:
Die Lösung opfert also die Anzahl der Durchläufe, um die Geschwindigkeit jedes einzelnen Durchlaufs zu verbessern. (Es wäre allerdings gut, wenn Sie auch gewarnt würden, wenn das Dokument noch nicht stabil ist.) Auch wenn es keine perfekte Lösung ist, bin ich davon überzeugt, dass dies angesichts der Natur von TeX (und es ist unwahrscheinlich, dass sich TeX selbst in dieser Hinsicht in absehbarer Zukunft ändern wird) die beste mögliche Alternative ist.
Es gibt auch das mathstyle
Paket (siehe Diskussion hier), das umgeht, \mathchoice
indem es alle Trennzeichen im Mathematikmodus nutzt (abernicht \(
offensichtlich!) und fügen eine Logik ein, um den Überblick über den aktuellen Mathematikstil zu behalten, der nicht mit TeX übereinstimmt. Aber wie inAdityas Kommentar hier, es gibt Fälle, in denen es das Verhalten von TeX nicht vorhersagen kann. Zum Beispiel bei der Verwendung von \over
, \atop
TeX-Primitiven. (Der Kommentar ist allerdings 5 Jahre alt. Vielleicht ist er inzwischen besser geworden?)
Die beste Lösung besteht also darin, die Anzahl \mathchoice
der Verschachtelungsebenen zu reduzieren (beachten Sie, dass a in , , \mathchoice
enthalten ist ).\ThisStyle
\text
\mathpalette
) nach Möglichkeit zu reduzieren (z. B.Ich habe ein paar redundante \TextStyle
s in der Vorgängerfrage entfernt), oder wenn Sie den mathematischen Stil mit gesundem Menschenverstand ableiten können, könnten Sielokal neu definieren \mathchoice
, um es kurzzuschließen.
Alles in allem ist es ein überraschendes Ergebnis. Dies ist das erste Mal, dass ich etwas mit LaTeX machen wollte und es sich als unpraktisch herausstellte. Außerdem \mathchoice
bin ich beim Herumprobieren auf alle Schrecken von Makrosprachen gestoßen, bei denen man nie genau weiß, was in welcher Reihenfolge expandiert. (Schauen Sie sich einfach die „klassische“ Methode an, \expandafter\expandafter\expandafter\expandafter\expandafter...
nämlichdiese Lösung, und Sie wissen, dass etwas nicht stimmt.) Und schließlich \mathchoice
scheint die Semantik von für Software aus den Siebzigern etwas ineffizient zu sein, selbst wenn ihr eigentlicher Zweck nur darin besteht, ein einzelnes benutzerdefiniertes Symbol zu setzen ...