The command \ifthenelse is fragile. What's a good definition of the term? A command is fragile when it produces uncanny error messages when used in a moving argument. Moving arguments are:
- the mandatory argument to a title (
\chapter, \section and similar) or to \caption, unless the optional argument is used;
- the optional argument to a title or to a
\caption, if used.
The standard method for coping with fragile commands in moving arguments is to prefix them with \protect.
A user defined command can be made robust by defining it with \DeclareRobustCommand.
\documentclass{article}
\usepackage{ifthen}
\newcommand{\mytest}[1]{%
\ifthenelse{\equal{#1}{a}}{yes}{%
\ifthenelse{\equal{#1}{b}}{no}{%
}}}
\DeclareRobustCommand{\myrobusttest}[1]{%
\ifthenelse{\equal{#1}{a}}{yes}{%
\ifthenelse{\equal{#1}{b}}{no}{%
}}}
\begin{document}
Troublesome construction: \mytest{a} and \mytest{b}.
Troublesome construction: \myrobusttest{a} and \myrobusttest{b}.
\section{Troublesome construction: \protect\mytest{a} and \protect\mytest{b}.}
\section{Troublesome construction: \myrobusttest{a} and \myrobusttest{b}.}
\end{document}
For hyperref, you can use \protected\def instead:
\documentclass{article}
\usepackage{ifthen}
\usepackage{hyperref}
\protected\def\mytest#1{%
\ifthenelse{\equal{#1}{a}}{yes}{%
\ifthenelse{\equal{#1}{b}}{no}{%
}}}
\begin{document}
Troublesome construction: \mytest{a} and \mytest{b}.
\section{Troublesome construction: \mytest{a} and \mytest{b}.}
\end{document}
If the argument to \mytest is expected to be a string (no special character or command), the following will work also with hyperref:
\documentclass{article}
\usepackage{xparse}
\usepackage{hyperref}
\ExplSyntaxOn
\NewExpandableDocumentCommand{\mytest}{m}
{
\str_case:nn { #1 }
{
{a}{yes}
{b}{no}
}
}
\ExplSyntaxOff
\begin{document}
Troublesome construction: \mytest{a} and \mytest{b}.
\section{Troublesome construction: \mytest{a} and \mytest{b}.}
\end{document}
The advantage is that you get no warning at all from hyperref about Token not allowed and that the list of cases is easily extended to three or more.
With a further level of abstraction, you can define as many similar tests as you want.
\documentclass{article}
\usepackage{xparse}
\usepackage{hyperref}
\ExplSyntaxOn
\NewDocumentCommand{\definetest}{mm}
{
\NewExpandableDocumentCommand{#1}{m}
{
\str_case:nn { ##1 } { #2 }
}
}
\ExplSyntaxOff
\definetest{\mytest}
{
{a}{yes}
{b}{no}
}
\begin{document}
Troublesome construction: \mytest{a} and \mytest{b}.
\section{Troublesome construction: \mytest{a} and \mytest{b}.}
\end{document}
\section{Troublesome construction: \protect\mytest{a}.}. – Sep 06 '18 at 15:51\ifthenelseis not expandable. You can try\section{Troublesome construction: \protect\mytest{a}.}and that should do the right thing in most situations. Another possibility would be to try and re-write the conditional expandably. – moewe Sep 06 '18 at 15:51protect(i.e., rewrite as\section{Troublesome construction: \protect\mytest{a}.) worked completely.Moreover, the link to xstring functions in section/paragraph headers was also helpful in particular because it pointed to Fragile and Robust commands. I rewrote the macro using
– Jim Ratliff Sep 06 '18 at 16:20\DeclareRobustCommand\mytest[1]{…and that also worked, and that's better for the end user.\documentclass{article} \newcounter{myfoo} \begin{document} \tableofcontents \stepcounter{myfoo} \section{Foo \themyfoo} \end{document}to\section{Foo \protect\themyfoo}in the TOC. So you should check carefully whether a robust command is appropriate or whether you are better of trying to get\mytestto be expandable. – moewe Sep 06 '18 at 19:55