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.

With

\edef\x{\ifnum0=0\else\fi}

being \relax and with

\def\y{\relax}

we see that \ifx\x\y is false. Why?

See also \ifcsname when it isn't apparent that the command is \relax'ed.

share|improve this question
2  
See also this related chat discussion‌​. Apparently the special relax has a different definition than the normal one. –  Martin Scharrer May 26 '12 at 11:26
    
On the other hand, \expandafter\ifx\x\relax is true. This works for all primitives that have a frozen version and therefore appear twice in the equivalence table. With LuaTeX, you can create additional copies of primitives using tex.enableprimitives, and they show the same behavior. –  Philipp May 26 '12 at 14:51
    
Generally speaking, \ifx only looks one level deep: it checks whether all tokens have the same indices into the equivalence table, but does not check whether they have the same meaning. The same works with \let\foo=\relax: Now \foo is a token with the meaning of \relax but a different name. –  Philipp May 26 '12 at 14:55
    
Does pdfTeX have something similar to tex.enableprimitives? –  Ahmed Musa May 27 '12 at 0:00

2 Answers 2

up vote 12 down vote accepted

Let's look at the transcript of an interactive session with TeX.

> tex
This is TeX, Version 3.1415926 (TeX Live 2011)
**\relax

*\def\x{\relax}

*\edef\y{\ifnum0=0\fi}

*\show\x
> \x=macro:
->\relax .
<*> \show\x

?      

*\show\y
> \y=macro:
->\relax .
<*> \show\y

? 

*\ifx\x\y\message{EQUAL}\else\message{UNEQUAL}\fi
UNEQUAL

*\edef\z{\ifnum0=0 \fi}

*\show\z
> \z=macro:
->.
<*> \show\z

? 

*\bye
No pages of output.
Transcript written on texput.log.

Why aren't \x and \y equivalent? And why aren't \y and \z equivalent in the first place?

The conditionals

\ifnum0=0\fi

or

\ifnum0=0\else\fi

are pretty much the same and the fact that \y becomes nonempty stems down from another precaution that TeX takes against premature expansion.

When TeX is looking for a <number> it expands tokens as it goes. But in this case it finds a \fi or an \else that matches the \ifnum while the search for the second number to test is still unfinished. Were it to expand the \fi or \else everything bad might happen. So, in this cases, TeX inserts a "safe" token that it represents on the terminal with \relax but is in fact not the same \relax that we know and are allowed to use. For instance, you can't redefine this token:

This is TeX, Version 3.1415926 (TeX Live 2011)
**\relax

*\edef\x{\ifnum0=0\fi}

*\expandafter\def\x{Something}
! Missing control sequence inserted.
<inserted text> 
                \inaccessible 
<*> \expandafter\def\x
                      {Something}

One is not allowed to feed the "frozen relax" token to \def, as it is evident from the above interactive session.

The problem does not show with

\edef\z{\ifnum0=0 \fi}

because the lookup for the <number> is terminated by the space token (which is then ignored). Therefore this is just a complicated way to say

\def\z{}

Note. With \edef\Z{\ifnum0=1\else\fi} or \edef\Z{\ifnum0=1\fi} the expansion of \Z would be empty, because the "frozen relax" token becomes part of the "true branch" and so it disappears.

When is TeX inserting the "frozen relax"?

TeX keeps track of the nesting of conditionals and the insertion of the frozen relax happens when an \else or \fi is encountered at the same level as the conditional it's being evaluated and the process of expansion for this evaluation hasn't yet finished.

So, for instance, TeX adds one in

\ifnum0=1\else\fi

because a <number> is collected by expanding the following tokens. Another case is

\if\fi

which results in an empty expansion because two frozen relax tokens are inserted, which are equal as far as \if is concerned. Also

\if\relax\fi

inserts a frozen relax, but again, \if compares \relax to the frozen relax token and the test returns truth.

share|improve this answer

In simpler language, there are two TeX scanning rules to keep in mind:

1) The expansion of \ifnum...\fi is empty a if the test is false, \relax (frozen) otherwise.

   true condtion -> \relax (frozen)
   false condition -> empty 

2) TeX when reading integers will read until it finds something unexpandable such as a space.

Consider the following MWE:

\tracingall
\count0=5
\count13=5
\count0=2\ifnum\count0=\count1 3 some words\fi9\par%false->empty 
\the\count0 %29
\bye

Here, we see both rules in operation, TeX is trying to put a value into \count0=2, but continues to scan until it finds an unexpandable token. It encounters the conditional. It evaluates the condition (which is false) and as per rule 1) the ifnum..\fi are let to empty. The scanning is then completed and count0=2{empty}9, hence 29.

Modifying the MWE to complete the discussion (\ifnum\count0=\count13).

\tracingall
\count0=5
\count13=5
\count0=2\ifnum\count0=\count13 some words\fi9\par% true>\relax  prints some words 9
\the\count0 % has the value of 2
\bye

If you have a conditional in an \edef, it behaves exactly the same way as edef expands its contents. The second part of your question stems from the fact that the relax inserted by TeX is a "frozen" relax and hard-coded into the engine. (See example at the bottom of http://tex.stackexchange.com/a/57404/963).

a It appears that egreg and David Kastrup call this emptiness and the \relax an unfinished conditional.

share|improve this answer
    
Sorry, but your assertion about the expansion of \ifnum is still incorrect. The "frozen relax" is inserted only in some cases and \edef\x{\ifnum0=0 \else\fi} results in an empty meaning for \x even if the test is true. –  egreg May 26 '12 at 14:10
    
@egreg empty meaning or space? Can you expand on the only? –  Yiannis Lazarides May 26 '12 at 14:18
    
The "frozen" relax is inserted only when TeX finds an \else or \fi at the same level as the conditional it's evaluating, while collecting tokens to proceed to the evaluation. In the example I've given the expansion of \x is empty, because the space after the second 0 is ignored by rule. –  egreg May 26 '12 at 14:25

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.