4

It is my understanding that in \ifx\x\y xx \else yy \fi, \ifx does NOT expand its arguments. If you want \ifx to compare the expanded values of \x and \y, then we need to do the expansion ourselves before feeding them to \ifx:

\edef\xpndX{\x}
\edef\xpndY{\y}
\ifx\xpndX\xpndY xx \else yy \fi

as\edef does this expansion for us. This is frequently the case when \x and \y are the arguments in a macro so we really have no idea what kind of quantity they represent.

I was adapting a code snippet I found in user2478's answer to the TeX-SE question Why does this simple \ifx test fail? and came up with the following MWE:

\documentclass{article}
\usepackage[svgnames]{xcolor} % to get named colors

\begin{document}

\chardef\mysteryletter=`H
% loop through A-Z to find out the mystery letter
\newcount\currentchar

\currentchar=`A
\loop
  \chardef\temp=\the\currentchar
  \edef\tmp{\temp}%
  \ifx\mysteryletter\temp {\color{Red}\bf\temp}\else\temp\fi
  \advance \currentchar by 1
  \unless\ifnum \currentchar>90
\repeat

\end{document}

which, when compiled, generated the output:

enter image description here

which actually is the desired output, but it should NOT have been! I added the statement \edef\tmp{\temp} to get the 'expanded' version of \temp intending to change the \temp argument to the \ifx command to \tmp but had not when this document was compiled. Lo and behold, the desired result was printed out! This lead me to believe that the expansion performed by the \edef\tmp{\temp} statement was not required, so it was commented out and the document recompiled. This gave the wrong result; the letter H was not bold or red

enter image description here

I note that removing the comment character from the end of the \edef command had the expected affect of adding a space between each letter, but did not prevent the 'H' from being found and highlighted.

So my question is this: How does the unused expansion of \temp by the \edef statement change the comparison performed by the \ifx command? What am I missing here?

  • "Lo and behold", not "low and behold" – Hammerite Apr 27 at 22:25
  • 1
    \chardef\temp=\the\currentchar should always be \chardef\temp=\currentchar. There's no point in using \the (besides the desire of seeing your code break loose). – egreg Apr 28 at 11:14
  • @egreg: Very true, but such things are not always bad things when it leads to new insight. Thanks for the comment. – OneMug Apr 28 at 14:48
8
  \chardef\temp=\the\currentchar
  \edef\tmp{\temp}%

tokens defined via \chardef are not expandable, so \edef\tmp{\temp} is the same as \def\tmp{\temp}

It is not clear why you do not expect \ifx\mysteryletter\temp not to be true if the two tokens are both defined via \chardef with the same number?

I guess your modified version was equivalent to

  \chardef\temp=\the\currentchar
  \ifx\mysteryletter\temp 

There the \ifx test happens before the assignment while looking to end the number, you need

  \chardef\temp=\the\currentchar\relax
  \ifx\mysteryletter\temp 

or

  \chardef\temp=\currentchar
  \ifx\mysteryletter\temp 

So your \edef was just acting like \relax terminating the \chardef assignment.

  • Thanks for the fast response. Still trying to figure out how to use the TeX-SE question and comment editors, please be patient. I had planned on converting this snippet into a \def\scanAlpha#1{... so I coded it the way I did expecting the macro argument to be used in the \ifx to be somewhat unknown at execution time, say be using scanAlpha{X} which would make the argument to the \ifx different from using the \chardef as in the snippet. – OneMug Apr 27 at 16:58
  • As stated, removing the \edef and using either \chardef\temp=\the\currentchar\relax or \chardef\temp=\currentchar works just fine. Aah, such are the mysteries of \relaxing. Not sure if I will ever figure out how to \relax. Thanks again for this answer. – OneMug Apr 27 at 17:19
  • 3
    @OneMugit'its not really the \relax just that expansion happens when looking for a number, \count0=1\ifx ab 2\else 3\fi sets count0 to 13 with the ifx test happening before the assignment, but \count0=1 \ifx ab 2\else 3\fi sets count0 to 1 – David Carlisle Apr 27 at 17:32
  • Thanks for this illustration. I had not realized that a numeric assignment was so 'aggressive'. I take it that this expansion would continue even farther if that expansion kept producing more numbers, that is, continue until a non-number token was encountered, right? One other issue here, the assignment in your example generates a decimal number. Is it possible to generate numbers in other bases, hexadecimal for instance? – OneMug Apr 28 at 14:24
  • After some reflection about how \ifx expands its arguments, it seems that the statement I made in my question that `` \ifx does NOT expand its arguments'' is not strictly correct, as it must surely expand them at least once if that argument is a control sequence. Is that correct? – OneMug Apr 28 at 14:41

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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