TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

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.

share|improve this question
up vote 12 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.

share|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

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}
share|improve this answer
    
Nice indeed! Is there a reason for all those ~s? – Hendrik Vogt Nov 11 '10 at 9:19
2  
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}

\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.

share|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 '12 at 12:00

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}
share|improve this answer
    
I went down this path, but then it turned out that it can't do the following, for example. If I want to replace the first argument to \rule{1em}{2em} by an \IfEqCase, to output 5em or 10em etc., it won't work. As far as I can tell, this is because, as the xstring manual says, these macros are not purely expandable. I'm assuming this means that there is nothing we can do to have the \IfEqCase as the first argument to \rule be expanded before \rule is processed. So we can't use this as freely as \if, \else, \fi, etc. Correct me if I'm wrong! – Evgeni Sergeev Feb 8 at 10:02
    
@EvgeniSergeev: Sorry, but I am not very knowlegeable in regards to expansion related issues. I'd recommend you post a new question. I think you can do what you want using the optional parameter at the end of most of the xstring macros, but would need a MWE to make an attempt. – Peter Grill Feb 8 at 10:25
    
It seems the optional parameter isn't available for the comparison macros in xstring (I've just tried it to make sure). I'm more or less convinced that this will require too many tricks to make work, so I'll go with one of the other options. – Evgeni Sergeev Feb 8 at 10:41

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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