Was ist der Befehl \span?

Was ist der Befehl \span?

Ich bin ein paar Mal auf das Primitiv gestoßen \span. Ich habe den Eindruck, es ist im TeX-Programm definiert, nicht einmal in plain.tex. Ist das richtig? Und wastutmacht dieser Befehl und wozu dient er?

Antwort1

Das Grundelement \spanhat zwei sehr unterschiedliche Bedeutungen, je nachdem, ob es in der Präambel \halignoder im Hauptteil erscheint.

Wenn es in der Präambel steht, also vor dem ersten, \crbedeutet es, das folgende Token zu „erweitern“. Wenn es im Textkörper erscheint, beendet es die aktuelle Zelle, verbindet sie aber mit der folgenden. In diesem Fall steht es normalerweise in Kombination mit \omit.

Das einfachste Beispiel ist

\halign{\hfil#\tabskip1em&#\hfil\cr
  a&b\cr
  c\span d\cr
}

wobei die zweite Zeile nur eine Zelle enthält. Die Ausgabe lautet

Bildbeschreibung hier eingeben

ohne \tabskipAbstand zwischen „c“ und „d“, da die zweite Zeile nur aus einer Zelle mit \hfilInhalt davor und danach besteht, TeX dies jedoch \tabskipbei der Bestimmung der Zellenbreite berücksichtigt.

Normalerweise fügt man jedoch auch hinzu, \omitum dieSieUndgegenTeile (Siebezieht sich auf das, was vorher kommt #,gegenzu dem, was darauf folgt).

Wenn TeX eine Präambel für liest, \halignerweitert es Token nicht, es sei denn, es findet \tabskip(wenn es Token erweitert, um die entsprechende Verbindungsspezifikation zu finden). Die Erweiterung eines Tokens kann erzwungen werden, indem ihm ein vorangestellt wird \span.

Ein Beispiel ist inamsmath.sty

\def\align@#1#2{%
    \inalign@true \intertext@ \Let@ \chardef\dspbrk@context\z@
    \ifingather@\else\displ@y@\fi
    \let\math@cr@@@\math@cr@@@align
    \ifxxat@\else \let\tag\tag@in@align \fi
    \let\label\label@in@display
    #1% set st@r
    \ifst@rred\else \global\@eqnswtrue \fi
    \measure@{#2}%
    \global\row@\z@
    \tabskip\eqnshift@
    \halign\bgroup
        \span\align@preamble\crcr
        #2%
}

Dies ist ein Hilfsmakro, das für alignund Freunde verwendet wird; die Präambel wird ein für alle Mal im Makro definiert\align@preamble

\def\align@preamble{%
   &\hfil
    \strut@
    \setboxz@h{\@lign$\m@th\displaystyle{##}$}%
    \ifmeasuring@\savefieldlength@\fi
    \set@field
    \tabskip\z@skip
   &\setboxz@h{\@lign$\m@th\displaystyle{{}##}$}%
    \ifmeasuring@\savefieldlength@\fi
    \set@field
    \hfil
    \tabskip\alignsep@
}

Dies vereinfacht die Definition von erheblich \align@, indem ein großer Teil des Codes in ein Makro eingefügt wird. Es ermöglicht auch die Änderung des Verhaltens von aligndurch Modifizierung \align@preamble(sieheIst es möglich, ungeraden Spalten implizit das Präfix {} zuzuweisen?).

Der LaTeX-Kernel verwendet hierfür eine andere Methode tabular, da er die Präambel nach seinen Regeln aufbauen muss, also aus einer Kombination von lcrpZeichen usw.

Die zweite Verwendung für \spanist das Zusammenführen von Spalten in einem \halign. In Plain TeX finden wir\multispan

\def\multispan#1{\omit \mscount#1\relax
  \loop\ifnum\mscount>\@ne \sp@n\repeat}
\def\sp@n{\span\omit\advance\mscount\m@ne}

das tut es \omitund fügt so viele \span\omitPaare hinzu, wie im Argument angegeben sind (minus eins); \multispan{1}ist also äquivalent zu \omit, \multispan{2}zu \omit\span\omitund so weiter. Das \multicolumnMakro von LaTeX basiert auf der gleichen Idee

% latex.ltx, line 5053:
\long\def\multicolumn#1#2#3{\multispan{#1}\begingroup
  \@mkpream{#2}%
  \def\@sharp{#3}\set@typeset@protect
  \let\@startpbox\@@startpbox\let\@endpbox\@@endpbox
  \@arstrut \@preamble\hbox{}\endgroup\ignorespaces}

Zuerst wird dies ausgeführt \multispan{#1}(genau wie in Plain definiert) und anschließend wird eine „lokale“ Ausrichtungspräambel erstellt, wobei dieselben Elemente \@mkpreamverwendet werden, die tabularauch arrayzum Auswerten des obligatorischen Arguments verwendet werden.

Warum verwendete Knuth dasselbe Primitiv für zwei sehr unterschiedliche Bedeutungen? Um Platz zu sparen; TeX wurde geschrieben, als der Computerspeicherplatz knapp war und es wichtig war, eine Definition einzusparen. Da nur in (oder natürlich ) \spanvorkommen kann , ist das kein Problem.\halign\valign

Eine abwegige Verwendung von \spanin der ersten Bedeutung findet sich in der Lösung der Übung 20.16 im TeXbook

Folgendes sollte man nicht zu ernst nehmen, aber es funktioniert:

{\setbox0=\vbox{\halign{#{\c\span\d}\cr
       \let\next=0\edef\next#1{\gdef\next{\b#1}}\next\cr}}}
 \let\a=\next

In der Übung geht es darum, zu definieren, \adass es äquivalent zu \b(vollständig erweitert) gefolgt von \c(nicht erweitert) und von \d(nur einmal erweitert) ist, ohne \noexpandund zu verwenden \the. Wenn wir zum Beispiel haben

\def\foo{xy\baz}
\def\baz{z}
\def\b{\foo\foo}
\def\c{--}
\def\d{\baz}

Wir wollen \aals Ersatztext definieren

xyzxyz\c\baz

Der \setbox0=\vbox{Teil ist einfach zu verwenden, \halignohne Ausgabe. Jetzt wertet TeX die \halignPräambel als aus #{\c\baz}\cr, da \spaneine einstufige Erweiterung von bewirkt \d. Die einzige Zelle enthält

\let\next=0\edef\next#1{\gdef\next{\b#1}}\next

das gemäß den Regeln anstelle von #in der Präambel verwendet wird, so dass der Eingabestrom wird

\let\next=0\edef\next#1{\gdef\next{\b#1}}\next{\c\baz}\cr

Das \crbeendet die Zelle einfach, es ist also nicht relevant. Wegen wird nicht erweiterbar, also \let\next=0wird es so definiert, als ob es gewesen wäre\next\edef\next

\def\next#1{\gdef\next{<full expansion of \b>#1}}

und wird daher \next{\c\baz}pflichtbewusst ausführen

\gdef\next{<full expansion of \b>\c\baz}

und das Finale \let\a=\nextgibt allem den Rest.

Das erklärt gut, dass \spannureinsSchritt der Erweiterung.


Eine andere Lösung mit e-TeX (es verwendet schließlich nicht \noexpandund \the) wäre

\edef\a{\b\unexpanded\expandafter{\expandafter\c\d}}

verwandte Informationen