![使用 \ifdim 出现意外的条件分支](https://linux22.com/image/247120/%E4%BD%BF%E7%94%A8%20%5Cifdim%20%E5%87%BA%E7%8E%B0%E6%84%8F%E5%A4%96%E7%9A%84%E6%9D%A1%E4%BB%B6%E5%88%86%E6%94%AF.png)
我对以下代码有疑问:
\newtoks\sectoks
\sectoks={\noindent}
\newtoks\subsubjectstyle
\subsubjectstyle={\emitsectglue 1\the\sectoks}
\newtoks\postsectoks
\postsectoks={\par\smallskip\noindent\kern-1sp\hskip1sp}
\long\def\subsubject#1\par{%
{\the\subsubjectstyle#1}\the\postsectoks}
\def\emitsectglue#1{%
\ifdim\lastskip=1sp
\nobreak
\else
\vskip0pt plus#1\baselineskip
\penalty-\numexpr#1*100+50\relax
\vskip0pt plus-#1\baselineskip
\vskip#1\baselineskip
\fi}
\long\def\blockquote#1\eol{%
\emitsectglue 1
\begingroup
\raggedright\narrower\noindent #1
\smallskip
\endgroup\noindent}
\tracingall
\subsubject
The following subsubject will choose the first if's true-branch.
\subsubject
But the following blockquote will not. Why is that?
\blockquote
Be conservative in what you send, liberal in what you receive
\eol
\bye
当使用该\subsubject
命令后跟另一个命令时\subsubject
,宏将按预期工作并且不会添加垂直粘贴和负惩罚。
但是,当使用另一个命令使用完全相同的代码时,突然\if
没有选择正确的分支。我不明白为什么会这样。
答案1
\relax
在之后添加\hskip1sp
:TeX 在寻找跳过规范时会扩展标记,并且在\blockquote
跟随时,规范尚未完成,因此扩展会\ifdim
在插入跳过之前进行评估。
如果\subsubject
如下,则没有问题,因为替换文本中的第一个标记是{
停止扩展的标记。
我会支持这一论点,\emitsecglue
并消除几个可能的虚假空间源:
\newtoks\sectoks
\sectoks={\noindent}
\newtoks\subsubjectstyle
\subsubjectstyle={\emitsectglue{1}\the\sectoks}
\newtoks\postsectoks
\postsectoks={\par\smallskip\noindent\kern-1sp\hskip1sp\relax}
\def\subsubject#1\par{%
{\the\subsubjectstyle#1}\the\postsectoks}
\def\emitsectglue#1{%
\ifdim\lastskip=1sp
\nobreak
\else
\vskip0pt plus#1\baselineskip
\penalty-\numexpr#1*100+50\relax
\vskip0pt plus-#1\baselineskip
\vskip#1\baselineskip
\fi}
\long\def\blockquote#1\eol{%
\emitsectglue{1}%
\begingroup
\raggedright\narrower\noindent #1%
\smallskip
\endgroup\noindent}
\subsubject
The following subsubject will choose the first if's true-branch.
\subsubject
But the following blockquote will not. Why is that?
\blockquote
Be conservative in what you send, liberal in what you receive
\eol
\bye