I give an answer below saying it's a bug in ifthen
package, but I think I'm going to reclassify it as a feature.
In unmodified LaTeX2e \(
\nd \)
are fragile commands and as such they should be preceded by \protect
if used in a moving argument (as the argument of \equal
).
\ifthenelse{\equal{\protect\(a\protect\)}{\protect\(a\protect\)}}{\typeout Y}{\typeout N}
does work as intended.
If you load the fixltx2e
package part of the core base distribution then \(
and \)
are made robust so you (and even I) might have expected that \protect
is not necessary. However the due to the way \ifthenelse
overloads the \( \)
syntax to be a boolean logic parenthesis rather than math start, \(
is made fragile again. The "fix" below locally gives \(\)
robust definitions however due to the "interesting" expansion order implemented in ifthenelse
This local redefinition applies to the entire predicate not just the arguments to \equal
and so the "fix" is entirely wrong as it removes the ifthenelse
definition of \(\)
entirely.
Sorry (if you want to take away the green tick I'd understand:-) but unless sleeping on it gives me a better idea, or another contributor has a better idea, I think the only thing I can do is more clearly document in ifthen
that if you use the ifthen
syntax commands (\(\)\or\and\isodd
etc inside an \equals
test, then you need to \protect
them.
Sorry it's a bug.
\ifthenelse
uses delimiters \(
and \)
to brackets boolean expressions. These are not made safe in the strings used by ifthenelse
\equal
test. The following inserts a local definition to make things safer,
\let\(\relax\let\)\relax
without this line you get the same error shown in your MWE.
\documentclass{article}
\usepackage{ifthen}
\makeatletter
\long\def\ifthenelse#1{%
\toks@{#1}%
\TE@repl\or\TE@or
\TE@repl\and\TE@and
\TE@repl\not\TE@neg
\TE@repl\OR\TE@or
\TE@repl\AND\TE@and
\TE@repl\NOT\TE@neg
\begingroup
\let\protect\@unexpandable@protect
\def\@setref##1##2##3{%
\ifx##1\relax\z@\else\expandafter##2##1\fi}%
\def\value##1{\the\csname c@##1\endcsname}%
\let\equal\TE@equal \let\(\TE@lparen \let\)\TE@rparen
\let\isodd\TE@odd \let\lengthtest\TE@length
\let\isundefined\TE@undef
\begingroup
\let\@tempa\relax\let\@tempb\relax
\let\(\relax\let\)\relax
\xdef\@gtempa{\expandafter\TE@eval\the\toks@\TE@endeval}%
\endgroup
\@gtempa
\expandafter\endgroup\ifTE@val
\expandafter\@firstoftwo
\else
\expandafter\@secondoftwo
\fi}
\makeatother
\ifthenelse{\equal{a}{a}}{\typeout Y}{\typeout N}
\ifthenelse{\equal{a}{b}}{\typeout Y}{\typeout N}
\ifthenelse{\equal{\(a\)}{\(a\)}}{\typeout Y}{\typeout N}
\ifthenelse{\equal{\(a\)}{\(b\)}}{\typeout Y}{\typeout N}
\stop
This produces
Y
N
Y
N
)
No pages of output.
on the terminal showing the tests worked.
ifthen
package obsolete?) andalgorithmicx
(http://ctan.org/pkg/algorithmicx) uses [ifthen
to condition on many levels. For example, using\State \Call{MqOpen}{\protect\(\aleph\protect\)}
works. Not exactly sure why\relax
makes it work though.