# What are the values for parameters of an \edef at the time of definition?

Suppose we have the following short document

\documentclass{article}

\def\foo#1{\if#1XX\else not X\fi}

\edef\bar#1{\if#1XX\else not X\fi}

\begin{document}
foo: X = \foo{X}, Y = \foo{Y}

bar: X = \bar{X}, Y = \bar{Y}
\end{document}


which results in

foo: X = X, Y = not X
bar: X = not X, Y = not X

The first case is quite simple to understand, expansion of \foo happens at the time the macro is called, #1 is replaced by X or Y, and the \if is executed with either of these two characters.

What is not so clear is the result of \bar. I understand that the expansion of \if here happens at the time the macro is defined and thus the concrete value of #1 not yet available; TeX leaves "holes" for the parameters in the expanded replacement text to be filled in later when the macro is actually called. But to properly expand the \if here, some value for #1 is needed.

The parameter doesn't seem to be just left empty, otherwise \bar shouldn't give not X, because \if XX would always be true. They also don't seem to be \relaxed, as

\edef\baz#1{\ifx#1\relax yes\else no\fi}


always gives no.

Then what values are used for the parameters at the time of definition?

When TeX does \edef<macro><parameter text>{1<replacement text>}2 it sets aside the <macro> the replacement text and {1, then does full expansion to <replacement text> until finding the matching }2. Finally it does

\def<macro><parameter text>{<full expansion of the replacement text>}


The full expansion of \if#1XX\else not X\fi is not X, because # and 1 are different character tokens (by character code).

Thus your \edef becomes the same as

\def\bar#1{not X}


As another example,

\edef\rightbracestring{\string}}


is perfectly legal, even if it appears to have unbalanced braces, because when the expansion is being done, the first } has already been tokenized as }12 when encountered. This proves that TeX doesn't first absorb the whole <replacement text>, but performs expansion just like in normal circumstances, with the difference that the matching }2 stops the process and resumes the assignment.

• That's interesting, I've always thought #1...#9 are considered a single token, just like control sequence names. Is that behavior, that the parameter text is expaned before the final brace is found, documented? I'm having trouble finding it in the TeXbook Sep 29, 2018 at 9:04
• @siracusa That's a simplification good for the purpose of presenting the basics of macro definitions. As far as TeX is concerned, #1 is two tokens when examining a definition for storing it in memory. I'm afraid you have to peruse tex.web or perhaps the simpler TeX by topic, as the TeXbook is quite reserved on the topic. Sep 29, 2018 at 19:30

I would say that it compares # with 1 hance always goes for the false branch. (Compares second test where it compares # with # and chooses true branch)

\edef\bar#1{\if#1#1 (TRUE)\else #1 (FALSE)\fi}

\show\bar

\edef\bar#1{\if##1 (TRUE)\else (FALSE)\fi}

\show\bar

\bye


Gives

> \bar=macro:
#1->#1 (FALSE).
l.3 \show\bar

> \bar=macro:
#1->1 (TRUE).
l.8 \show\bar

• try also \edef\bar#1{\if###1 (TRUE)\else (FALSE)\fi}, \bar X.
– user4686
Sep 28, 2018 at 15:58
• Yes, if one tries (with pdftex) \edef\bar#1{\unless\if#1XX\else not X\fi}, \show\bar will output that \bar is a macro doing #1->XX. Sep 28, 2018 at 16:11
• @egreg good test case indeed.
– user4686
Sep 28, 2018 at 16:16