命令 \span 是什麼?

命令 \span 是什麼?

我已經遇過\span幾次原始人了。我的印像是它是在 TeX 程式中定義的,甚至在plain.tex.是對的嗎?還有什麼該命令的作用是什麼?

答案1

\span如果原語出現在序言\halign或正文中,則它具有兩種截然不同的意義。

如果它位於序言中,即在第一個標記之前,\cr則表示「擴展」以下標記;如果它出現在正文中,則會結束目前儲存格,但將其與下一個儲存格合併。在這種情況下,它通常與 結合使用\omit

最簡單的例子是

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

其中第二行只有一個儲存格。輸出將是

在此輸入影像描述

「c」和「d」之間沒有\tabskip間距,因為第二行只是一個包含\hfil前後內容的單元格,但 TeX 將考慮這一點\tabskip來確定單元格的寬度。

然而,通常情況下,\omit為了刪除v部分 (指的是之前發生的事情#v到其後的內容)。

當 TeX 讀取序言時,\halign它不會擴展標記,除非找到\tabskip(當它擴展標記以找到適當的黏合規範時)。可以透過在令牌前​​面新增 來強制擴展令牌\span

一個例子是amsmath.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%
}

這是一個用於align和朋友的幫助宏;前導碼在巨集中一次定義\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@
}

\align@透過將大量程式碼放入巨集中,這大大簡化了 的定義。它還允許align透過修改來改變行為\align@preamble(參見是否可以使奇數列隱式帶有前綴 {}?)。

LaTeX核心對 則使用不同的方法tabular,因為它需要根據其規則建立前導碼,即lcrp字元的組合等等。

的第二個用法\span是合併\halign.在 Plain TeX 我們發現\multispan

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

這樣做\omit並添加\span\omit與參數中所述一樣多的對(減去一個); so\multispan{1}相當於\omit, \multispan{2}to\omit\span\omit等等。 LaTeX 的巨集\multicolumn是基於相同的想法建構的

% 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}

它首先執行(與 Plain 中的定義完全相同),然後繼續使用和 所使用的\multispan{#1}相同內容建立「本地」對齊前導碼,以評估其強制參數。\@mkpreamtabulararray

為什麼高德納使用同一個原語來表達兩個截然不同的意義?為了節省空間; TeX 是在電腦記憶體空間不足的情況下編寫的,因此保存定義非常重要。由於\span只能出現在\halign(或者\valign,當然)中,所以這不是問題。

\spanTeXbook 練習 20.16 的解法中出現了第一種意義的不正當用法

以下內容不應該被過於認真地對待,但它確實有效:

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

這個練習是關於定義\a等於\b(完全擴展)後跟\c(未擴展)和 by \d(僅擴展一次)而不使用\noexpand\the。例如,如果我們有

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

我們想要定義\ahas 作為其替換文本

xyzxyz\c\baz

\setbox0=\vbox{部分只是使用,\halign沒有任何輸出。現在 TeX 將\halign前導碼評估為#{\c\baz}\cr,因為\span導致 的一級擴展\d。唯一的單元格包含

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

根據規則,它被用來代替#前導碼中的 ,這樣輸入流就變成了

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

剛剛\cr結束單元格,所以它不相關。由於\let\next=0,\next變得不可展開,因此\edef原因\next被定義為就好像它已被定義一樣

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

因此\next{\c\baz}將盡職盡責地執行

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

決賽\let\a=\next結束了一切。

這很好地解釋\span了僅擴充的步驟。


使用 e-TeX 的不同解決方案(畢竟它不使用\noexpandand )將是\the

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

相關內容