\bye
TeX 命令在 LaTeX 中被\begin{document}
和取代是否有技术原因\end{document}
?
我怀疑这背后一定有很好的技术原因,否则它就只是表面文章而已。我无法想象用两个单独的命令(一个 16 个字符,另一个 14 个字符)替换放在文档末尾的 4 个字符命令,这两个命令必须放在开头和结尾。
答案1
让我们看看它\enddocument
是如何定义的(参见latex.ltx
LaTeX“内核”):
\def\enddocument{%
\let\AtEndDocument\@firstofone
\@enddocumenthook
\@checkend{document}%
\clearpage
\begingroup
\if@filesw
\immediate\closeout\@mainaux
\let\@setckpt\@gobbletwo
\let\@newl@bel\@testdef
\@tempswafalse
\makeatletter \@@input\jobname.aux
\fi
\@dofilelist
\ifdim \font@submax >\fontsubfuzz\relax
\@font@warning{Size substitutions with differences\MessageBreak
up to \font@submax\space have occurred.\@gobbletwo}%
\fi
\@defaultsubs
\@refundefined
\if@filesw
\ifx \@multiplelabels \relax
\if@tempswa
\@latex@warning@no@line{Label(s) may have changed.
Rerun to get cross-references right}%
\fi
\else
\@multiplelabels
\fi
\fi
\endgroup
\deadcycles\z@\@@end}
全面讨论正在执行的所有操作将非常乏味。在我看来,最有趣的活动包括:(a)\clearpage
刷新所有待处理浮点数的指令、(b) 关闭文件aux
,以及 (c) 检查某些交叉引用是否仍未解决;如果仍有未解决的引用,则会生成以下著名的警告消息,提示需要重新运行 LaTeX:
\@latex@warning@no@line{Label(s) may have changed.
Rerun to get cross-references right}%
\bye
(参见教科书第 357 页)的定义遵循完全不同的模型:
\outer\def\bye{\par\vfill\supereject\end}
\stop
最后,这里是David Carlisle 在评论中提到的宏的定义:
\def\stop{\clearpage\deadcycles\z@\let\par\@@par\@@end}
(\@@end
是“原始”命令的 LaTeX 内部版本\end
。)你能说出为什么 David 补充说“它永远不应该在普通的 [LaTeX] 文档中使用”吗?
答案2
这是语法上的原因。LaTeX 有环境的概念,而普通 TeX 中没有。环境document
是文档内容的外部环境。
文档的设置/配置与实际文档内容是分开的,这是在环境document
启动前的序言中完成的。序言会加载类和包,这在环境中是不允许的document
。
还\begin{document}
引入了文档初始化的概念,这在纯 TeX 中同样不存在。例如,文件.aux
被读入\begin{document}
(并再次签入)\end{document}
。
环境形式强制正确嵌套环境:
\begin{document}
\begin{table}
\begin{quote}
\begin{tabular}{l}
% Compare \bye vs. \end{document} here
\end{tabular}
\end{quote}
\end{tabular}
\end{document}
如果\bye
是结束文档的正常形式,那么它可以在其他环境中以语法正确的形式编写,请参阅上面的代码。但是,当写为时,错误的地方就变得显而易见了\end{document}
。