答案1
当你这样做
\begin{letter}{
M. Y. Friend \\
42 Some Rd \\
Someplace
}
LaTeX 确实
\@processto{\leavevmode\ignorespaces #1}}
在示例中,它变为
\@processto{\leavevmode\ignorespaces M. Y. Friend \\ 42 Some Rd \\ Someplace }
这将首先执行
\@xproc \leavevmode\ignorespaces M. Y. Friend \\ 42 Some Rd \\ Someplace \\@@@
根据 的定义\@xproc
,LaTeX 将把 到#1
为止的所有内容\\
以及到 为止#2
的所有内容视为\\@@@
\def\toname{\leavevmode\ignorespaces M. Y. Friend }
\def\toadddress{ 42 Some Rd \\ Someplace \\}
假设你这样做
\begin{letter}{M. Y. Friend}
相同的过程将导致调用
\@xproc \leavevmode\ignorespaces M. Y. Friend \\@@@
在这种情况下,#1
再次是直到第一个(且唯一的)的所有内容\\
,并且#2
是从\\
(排除)到的所有内容@@@
,因此它为空。
因此,有趣的情况是当\toaddress
不为空时:需要调用\@yproc
才能删除尾随\\
,并且调用确实是
\@yproc #1@@@
将成为
\@yproc \leavevmode\ignorespaces M. Y. Friend \\ 42 Some Rd \\ Someplace @@@
所以最终会
\def\toaddress{ 42 Some Rd \\ Someplace }
请注意,前导空格和尾随空格不会被省略。\opening
执行时,它们会“消失”,因为\toname
和\toaddress
是在的范围内排版的\raggedright
,恰好(第 192 行)
{\raggedright \toname \expandafter\\\toaddress \par}%
因此在示例中我们将得到
{\raggedright \leavevmode\ignorespaces M. Y. Friend \\ 42 Some Rd \\ Someplace \par}
由于\\
也一样\par
,因此在这种情况下,尾随空格被隐式的 抑制\unskip
。
为什么这么奇怪\expandafter
?因为用户可能希望收件人的姓名和地址之间有一些分隔,所以输入类似
\begin{letter}{
M. Y. Friend \\[1ex]
42 Some Rd \\
Someplace
}
应用与上述相同的推理,可以看到在这种情况下 LaTeX 确实
\def\toaddress{[1ex] 42 Some Rd \\ Someplace }
如果没有\expandafter
以下\\
就不会看 [1ex]
。
文档确实说了
更好的解决办法是进行适当的解析,但是……
答案2
看看下一行\@xproc
的定义。
\long\def\@xproc #1\\#2@@@{\def\toname{#1}\def\toaddress{#2}}
\long\def\@yproc #1\\#2@@@{\def\toaddress{#2}}
有 #1 被 分隔\\
,并且#2
被 分隔@@@
。因此只是第二个参数的分隔符。 (用于)@@@
的用法如下:如果包括则为非空,因为包括其余的\@xproc text\\@@@
\@processto
text
\\
#2
#2
text
然后是\\
。如果text
不包括\\
则为#2
空,因为#1
是整个,并且我们在和text
之间看不到任何内容。如果有人编写了一个包括 的宏,则此行为可能会被破坏,但宏程序员认为这种情况发生的概率较小。\\
@@@
text
\\@@@