Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

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?

share|improve this question
    
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
add comment

1 Answer

up vote 7 down vote accepted

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:

share|improve this answer
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
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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