[Tex/LaTex] Algorithmicx — How to use latex maths delimiters

algorithmicxdelimitersmath-mode

Today, I decided to migrate from using TeX [$..$] to LaTeX [\(..\)] delimiters for inline maths, and, as usual, fell off the cliff of my somewhat precarious understanding of TeXian gastroenterology, in the middle of an algpseudocode environment.

Here's my MWE:

\documentclass{article}
\usepackage{algpseudocode}
\begin{document}
\begin{algorithmic}[1]
\Procedure{Trigger Dispatching Scheduler}{}
\State \Call{MqOpen}{$\aleph$}
\State \Call{MqOpen}{\(\aleph\)\relax}
%\State \Call{MqOpen}{\(\aleph\)} % <== This one fails
\EndProcedure
\end{algorithmic}
\end{document}

Uncommenting the %-line causes it to fail (PdfLaTeX and XeLaTeX) with:

! Argument of \) has an extra }.
<inserted text> 
                \par 
l.14 \State \Call{MqOpen}{\(\aleph\)}
                                      % <== This one fails

What, if anything, am I doing wrong? If anyone could explain in fairly simple terms what's going on here, I'd be most grateful.

Best Answer

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.