In C, preprocessor macros can have unexpected effects because their arguments can be evaluated multiple times. For example, the following code:

#define MAX(a,b) ((a)>(b) ? (a) : (b))
int i = 5, j = MAX(i++, 0);


int i = 5, j = ((i++)>(0) ? (i++) : (0));

and the variable i will have the value 7—not 6 as expected—because the macro's arguments are repeated in the macro definition.

Does LaTeX have similar issues? For example, what would happen in the following:

\newcommand{\foo}[1]{#1 #1}

Would the side effects happen twice? If so, how can that be avoided? Can \edef be cleverly used to cause side effects to happen only once? Or \sbox (assuming the argument is something you want boxed)? Or maybe some way to automatically remove tokens that have side effects from #1?

Is this a problem in practice?


The side effect can occur in TeX as well. As far as I know there is no real way to avoid them. That is, if you produce something like you did in your example, there is no way to change \foo to accommodate that. Take the following example:

\def\foo#1{#1 #1}

This will produce x y, because first the #1s in foo are replaced by their replacement text (\temp) and then those are expanded one at a time. That means \switch is changed before the second \temp is expanded. In this simple example grouping would help. If we changed the definition of \foo to \def\foo#1{{#1}{#1}} then it would print x x. However, this stops working when we \gdef instead of \def \switch inside of \temp. The problem is, if we can't modify \temp then we can't really do anything about that in \foo. So if you pass a macro with side effects to a macro that uses that argument more than once, it can lead to problems.

  • Thank you for your answer. Can \edef or \sbox be used to eliminate the multiple side effects? See my revised question. Apr 8 '12 at 0:13

This is a common problem when dealing with float captions. For example, here's the definition of \@makecaption which is called by \caption (taken from article.cls):

  \sbox\@tempboxa{#1: #2}%
  \ifdim \wd\@tempboxa >\hsize
    #1: #2\par
    \global \@minipagefalse

The caption is set inside a box \@tempboxa, after which its tested for horizontal width. If it fits, then the original box \@tempboxa is set, otherwise it is re-evaluated. The re-evaluation is performed to switch from centred (the default) to paragraph-style alignment of the caption. So, any \label or counter-related entries should be used with caution (especially if there's a contents for the floats created as well). Here's a small example:

enter image description here

  \caption{This is \mynewitem.}
  \caption{This is \mynewitem\ together with a lengthy caption that stretches more than one line.}

Resolutions to these problems are sometimes provided by manual work-around (which may vary on a case-by-case basis), or perhaps a package. Most solutions are provided by going back to the source and trying to understand the root of the problem, which invariably provide hints to possible work-arounds.

On a side-note. An interesting example of TeX's capability to be different from a programming language is presenting in David's answer to How do you swap the commands for two symbols?, suggesting that it's not always necessary to use a intermediate variable.

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.