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.

link|improve this question
feedback

4 Answers

up vote 10 down vote accepted

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.

link|improve this answer
1  
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
feedback

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

\prg_case_str:nnn {\doctype}
{
   {SomeString1} {some~ text~ here}
   {SomeString2} {some~ different~ text~ here}
}
{else~ clause}

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

\prg_case_int:nnn{2*5}{
  {5}{Small}
  {4+6}{Medium}
  {-2*10}{Negative}
}{Other}
link|improve this answer
Nice indeed! Is there a reason for all those ~s? – Hendrik Vogt Nov 11 '10 at 9:19
1  
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
feedback

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.

link|improve this answer
Thanks, this is pretty good looking. I may have to play with this in the future. – dsedivec Nov 8 '10 at 22:06
2  
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 at 12:00
feedback

Case statements can also be implemented with the xstring package:

enter image description here

\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}
link|improve this answer
feedback

Your Answer

 
or
required, but never shown

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