据我所知, 的目的\relax
是阻止宏吞噬后续材料(例如空格)。但{}
( \bgroup\egroup
) 具有相同的功能。为什么我们需要两者?
答案1
尝试以下几个例子:
\documentclass{article}
\begin{document}
\[
\begin{array}{rl}
+9mm & +9m^2 \\
[+9mm] & [+3m]^2 \\{}
+9mm & +9m^2 \\{}
[+9mm] & [+3m]^2 \\\relax
+9mm & +9m^2 \\\relax
[+9mm] & [+3m]^2
\end{array}
\]
\end{document}
- 如果您将
\\
其保留在那里,则将[+9mm]
被解释为的可选参数\\
并转换为垂直空间。 - 如果使用
{}
,则会在公式中插入“空值”,并且+
间距不正确。 - 这里只有带有的变体可以
\relax
正常工作,因为它实际上什么也不做。
可以使用非常相似的例子来表明这是和扩展等\relax
的正确终止符。\dimexpr
\numexpr
答案2
这个问题很难回答,因为这两个结构几乎在各个方面都不同,所以这是一个从哪里开始的问题。
\relax
是一个单独的标记,一个不可扩展的 TeX 原语,执行时不执行任何操作。
{}
是两个标记(假设标准 catcodes)标记一个 TeX 组或非分隔的宏参数。
\baselineskip =13pt\relax
停止\relax
长度解析器向前查看plus
和minus
组件,但不执行其他任何操作。\baselineskip =13pt{}
将以相同的方式定义baselineskip,但然后打开和关闭一个组,这可能会产生几种影响,最明显的是在数学模式下它将生成一个空的数学原子并影响周围原子的间距。{\let\section\relax...\immediate\write\@auxout{.. \section}}
使诸如\section
本地惰性的命令可以安全地(作为其自身)写入辅助文件。{\let\section{}...\immediate\write\@auxout{.. \section}}
做一些事情但不太可能做任何人想要的事情:-)\relax
是赋予由生成的新控件名称的定义,\csname
因此常用\expandafter\ifx\csname foo\endcsname\relax
来测试宏是否已定义。这显然与使用{}
$a+{}$
产生中缀间距,因为{}
生成一个数学原子。$a+\relax$
就像$a+$
和不产生中缀间距一样+
。
答案3
原因不止一个。
我来举个例子,看看哪个\relax
是好的,{}
哪个不是:
\def\mysize{144pt\relax} % when expanding \mysize we won't trigger
% expansion of the next token
\hbox to \mysize{\hfil abc\hfil}
当 TeX 处理\hbox
命令时,它会扩展后面的标记to
以找到所需的<dimen>
;它会找到144pt\relax
并根据语法规则让它\relax
消失(用 TeX 的术语来说,它是一个<filler>
);
\def\mysize{144pt{}}
TeX 会发现
\hbox to 144pt{}{\hfil abc\hfil}
这将是一场灾难。
当然也可以定义
\def\mysize{144pt }
但这样\mysize
就不能在文本中使用\unskip
。也许这是一个有点牵强的例子。
无论如何,\relax
实际上什么都不做,同时{}
打开和关闭一个组。
您提到\bgroup\egroup
等同于{}
:但事实并非如此;例如,带有 finds 参数的宏{}
将吸收一个空参数,而\bgroup\egroup
将吸收\bgroup
作为参数,留\egroup
在流中。同样,如果我们使用\relax
它,它将是一个标记。