11

These days, I’m more and more defining robust commands, e.g., using \newrobustcmd (etoolbox package) or \NewDocumentCommand (xparse package). Robust commands seem advantageous to me in many respects and, in fact, other people do think the same. To quote from the section of the xparse package documentation dedicated to the tools supporting the definition of non-robust (i.e. fully expandable) commands:

There are very rare occasion[s] when it may be useful to create functions using a fully-expandable argument grabber. To support this, xparse can create expandable functions as well as the usual robust ones. […] This facility should only be used when absolutely necessary; if you do not understand when this might be, do not use these functions!

Yet I’ve made the experience that robust commands have their pitfalls. Consider, for instance, the following minimal example:

\documentclass{article}

\usepackage{etoolbox}

\newrobustcmd*{\test}[1]{%
  \ifblank{#1}{blank}{not blank}%
}

\begin{document}

\tableofcontents

\section{\test{\empty}}

\end{document}

The output is rather unsatisfying since the decision of \test on the nature of its argument is context-dependent:

What shall I do in this and similar situations? Resort to \newcommand?

mhp
  • 8,692
  • 2
    Of course, the real issue here is the implementation of \section, which would be much better to write its argument \unexpanded. – Joseph Wright Jun 30 '12 at 16:35
  • @JosephWright: Definitely true! But how to ensure that all commands with moving arguments behave this way? – mhp Jun 30 '12 at 16:51

1 Answers1

11

The problem you encounter in your example is based on the fact that arguments of robust commands are not shielded from expansion at all. As a consequence, \test examines two different arguments: the token \empty in the section heading and the empty string in the table of contents. Nonetheless, you need not resort to defining \test as a fully expandable command. Use \newcommand in conjunction with \protecting (etoolbox package) to obtain a command that will be expanded only once:

\documentclass{article}

\usepackage{etoolbox}

\newcommand*{\test}[1]{%
  \protecting{\ifblank{#1}{blank}{not blank}}%
}

\begin{document}

\tableofcontents

\section{\test{\empty}}

\end{document}

The output is:

mhp
  • 8,692
  • 2
    I'm troubled: did you just answer yourself calling yourself "you"? (third word) – Bruno Le Floch Jul 01 '12 at 10:03
  • @BrunoLeFloch: OK, probably it would be better if I wrote ‘The problem I encounter in my example …’ to emphasize the fact that this is a self-answer. What do you think? – mhp Jul 01 '12 at 15:49
  • Oh, I should have put a smiley in my last comment. It really doesn't matter, I just found that odd :). Nice question and answer, by the way. – Bruno Le Floch Jul 01 '12 at 16:31
  • @BrunoLeFloch: :-) – mhp Jul 01 '12 at 18:56