Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

Why does the \ifx test give a different answer than \ifthenelse in the following simple example?

testclass.cls (without the head and tail):

\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

Now if I call commands \foo and \foofoo in a .tex file, I'll get the following output:

ifthen says yes

ifx says no

Why? Where's the difference? I thought that the following two would be equivalent:

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

Are there some expansion problems?

share|improve this question
    
Welcome to TeX.SX! A tip: You can use backticks ` to mark your inline code as I did in my edit. –  Christian Hupfer Jul 20 at 12:50

1 Answer 1

up vote 13 down vote accepted

First of all, after

\newcommand{\isempty}{\@empty}

the test

\ifx\isempty\@empty

will return false, because

  1. both \isempty and \@empty are macros, but
  2. they differ in their \long status.

However, also \newcommand*{\isempty}{\@empty} would make the test fail, because

  1. both \isempty and \@empty are macros, with the same \long status (both aren't \long), but
  2. they differ in their first level expansion, which is \@empty for \isempty and nothing for \@empty.

This assumes, of course, that your code is preceded by \makeatletter.

Why does \ifthenelse{\equal{\isempty}{\@empty} follow the true branch? Because the test does full expansion of the arguments of \equal. In both arguments the full expansion is empty. From the package documentation:

The ⟨string⟩s tested by \equal may be any sequence of commands that expand to a list of tokens. If these expansions are equal, then the proposition is true.

Basically, \ifx tests if the two tokens following it would give the same result when \meaning is applied to them. In the case of

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

doing \meaning\isempty would print

\long macro:->\@empty

while \meaning\@empty would print

macro:->

so you see they're different as far as \ifx is concerned.


If you don't have \makeatletter before your code, the situation is a bit more complicated:

  1. the full expansion of \@empty, which is six tokens long, is

    \spacefactor \@m empty
    
  2. since \isempty first expands to \@empty, the \ifthenelse test will follow the true branch anyway;

  3. The \ifx test will compare \isempty with \@, which returns false, so empty will disappear along with the true text and the false branch will be followed.

share|improve this answer
    
Ah, I see. Many thanks! Is there any way to make such a test go "yes" using \ifx? –  Mike Jul 20 at 14:22
1  
@Mike \let\isempty\@empty –  egreg Jul 20 at 14:31

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.