ifx 和 ifthenelse 之间的行为有何区别?

ifx 和 ifthenelse 之间的行为有何区别?

为什么\ifx测试给出的答案与\ifthenelse以下简单示例不同?

testclass.cls(不含头和尾):

\newcommand{\isempty}{\@empty}

\ifthenelse{\equal{\isempty}{\@empty}}
   {\newcommand{\foo}{ifthen says yes}}
   {\newcommand{\foo}{ifthen says no}}
\ifx\isempty\@empty
   \newcommand{\foofoo}{ifx says yes}
   \else\newcommand{\foofoo}{ifx says no}
\fi

现在,如果我在 .tex 文件中调用命令\foo\foofoo我将得到以下输出:

ifthen 说是

ifx 说不

为什么?区别在哪里?我以为以下两个是等效的:

\ifx\macroA\macroB\DoSomething\else\DoSomethingElse\fi
\ifthenelse{\equal{\macroA}{\macroB}}{\DoSomething}{\DoSomethingElse}

是否存在一些扩展问题?

答案1

首先,

\newcommand{\isempty}{\@empty}

考试

\ifx\isempty\@empty

将返回 false,因为

  1. \isempty都是\@empty宏,但是
  2. 他们的地位不同\long

然而,这也会\newcommand*{\isempty}{\@empty}导致测试失败,因为

  1. \isempty都是\@empty宏,状态相同\long(都不是\long),但是
  2. 它们在第一级扩展上有所不同,第一级扩展\@empty为,而 则为\isempty,并且 没有任何意义\@empty

当然,这假设您的代码前面有\makeatletter

为什么\ifthenelse{\equal{\isempty}{\@empty}遵循真正的分支?因为测试确实满的参数的展开\equal。在两个参数中,完整展开都是空的。来自包文档:

这 ⟨细绳测试的⟩s\equal可以是任何扩展为标记列表的命令序列。如果这些扩展相等,则命题为真。

基本上,\ifx测试后面的两个 token 在\meaning应用时是否会产生相同的结果。在

\makeatletter
\newcommand{\isempty}{\@empty}

执行\meaning\isempty将会打印

\long macro:->\@empty

while\meaning\@empty会打印

macro:->

因此您会看到,就其\ifx本身而言,它们是不同的。


如果你的代码之前没有这个\makeatletter,情况会稍微复杂一些:

  1. 的完整展开\@empty,长度为 6 个 token,是

    \spacefactor \@m empty
    
  2. 由于\isempty首先扩展为\@empty\ifthenelse测试无论如何都会遵循真正的分支;

  3. 测试\ifx\isempty与进行比较\@,返回 false,因此empty将与真实文本一起消失,并遵循错误分支。

相关内容