10

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?

  • 1
    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
10

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:

  • 1
    I'm troubled: did you just answer yourself calling yourself "you"? (third word) – Bruno Le Floch Jul 1 '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 1 '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 1 '12 at 16:31
  • @BrunoLeFloch: :-) – mhp Jul 1 '12 at 18:56

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.