# Making switch/case with etoolbox's \ifdefequal

I've got a define such as \def\doctype{SomeString}. \doctype can take on one of five values. I want to do something like a switch statement in a programming language, i.e. (pseudocode):

switch (\doctype) {
case 'SomeString1': some text here
case 'SomeString2': some different text here
...
}


(I don't need a default/else/otherwise case.) I tried doing this in LaTeX with:

\documentclass{article}

\usepackage{etoolbox}

\def\doctype{SomeString1}

\newenvironment{switchdoctype}[0]{%
\newcommand{\case}[2]{\ifdefequal{\doctype}{##1}{##2}{}}%
}{}

\begin{document}

\begin{switchdoctype}
\case{SomeString1}{some text here}
\case{SomeString2}{some different text here}
\end{switchdoctype}

\end{document}


This gives an error: ERROR: Argument of \@secondoftwo has an extra }. I gather this is some sort of problem with using \ifdefequal. How can I make this work? I suspect it's some trick of expansion but I can't make this work with my limited knowledge of [La]TeX; I'm interested in learning something from making this work.

MacTeX 2010 here, which is based on TeX Live 2010 AFAIK. Thanks!

P.S.: boolexpr has a \switch but I can't use it because it conflicts badly with etoolbox (and BibLaTeX depends on etoolbox as far as I can tell). I have reported this incompatibility to the author listed in boolexpr's documentation.

-

From your description, I think you want \ifdefstring, as you need to compare one macro with one definition of a macro. \ifdefequal is for testing two macros for equivalence.

-
Holy crap that is embarrassing. You are right. I knew of the existence of both of these commands in my head, but I obviously got them switched around in the course of coming up with this code. Thanks! –  dsedivec Nov 8 '10 at 22:06

Just for future reference, expl3 has nice switch/case statement constructs:

\str_case:nnF {\doctype}
{
{SomeString1} {some~ text~ here}
{SomeString2} {some~ different~ text~ here}
}
{else~ clause}


Variations are also provided with integers, dimensions, and token lists; e.g.,

\int_case:nnF{2*5}{
{5}{Small}
{4+6}{Medium}
{-2*10}{Negative}
}{Other}

-
Nice indeed! Is there a reason for all those ~s? –  Hendrik Vogt Nov 11 '10 at 9:19
In expl3 code, spaces are ignored, so if you want to print a string, ~ is used as a space. –  Will Robertson Nov 11 '10 at 11:20
Thank you very much! I skimmed expl3 the other day but didn't see anything that would help me. texdoc l3prg was just bringing up expl3.pdf. I have since learned to ask for source3 which appears to be a very comprehensive reference document. I'm excited to see all this stuff, especially all the standardized names. (And ignoring spaces also seems very kind to people writing commands.) If anyone in a position to do so reads this: it might be nice to mention the existence of source3 in the expl3 document. (My PDF reader didn't find that string.) –  dsedivec Nov 11 '10 at 19:23
@dsedivec Thanks for the feedback; I've added a pointer like you suggest. –  Will Robertson Nov 13 '10 at 13:07

For switching on identifiers, it's simplest to use the primitive \ifcase:

\documentclass{article}

\usepackage{etoolbox}

\def\typeone{1}
\def\typetwo{2}

\begin{document}

\let\doctype=\typeone

\ifcase\doctype
\or some text here %matches \typeone
\or some different text here % matches \typetwo
\else you didn't want an else case, but it's no trouble to put in
\fi

\end{document}


If you want to convert strings into your type numbers, you can use \csname ...\endcsname; e.g., \csname typeone\endcsname will expand into 1, matching the first case.

-
Thanks, this is pretty good looking. I may have to play with this in the future. –  dsedivec Nov 8 '10 at 22:06
No need for etoolbox here, I believe. –  Bruno Le Floch Apr 2 '11 at 18:13
@Brune: Or indeed Latex. (Only just noticed your comment) –  Charles Stewart Mar 29 '12 at 12:00

Case statements can also be implemented with the xstring package:

\documentclass{article}
\usepackage{xstring}

\newcommand{\CheckCase}[1]{%
\par\noindent%
\IfEqCase*{#1}{%
{Some String 1}{matched case 1}%
{Some String 2}{matched case 2}%
{Some String 3}{matched case 3}%
{Some String 4}{matched case 4}%
{Some String 5}{matched case 5}%
}[Did not match any given case!!]%
}%

\begin{document}
\CheckCase{Some String 1}
\CheckCase{Some String 2}
\CheckCase{Some String 3}
\CheckCase{Some String 4}
\CheckCase{Some String 5}
\CheckCase{Some String 6}
\end{document}

-