Implementing switch cases

The question asks to avoid packages, so while this is the method used by expl3 in \str_case:nnF I have recoded it with minimal support. The only package I've used is pdftexcmds, which is needed as the \pdfstrcmp primitive from pdfTeX is called \strcmp by XeTeX and has to be implemented in Lua for LuaTeX. This is easy enough to do without the package, but obscures the method: ask a separate question if required!

The general idea here is to set up a comparison loop in which the test is done expandably by \pdfstrcmp. The test string is passed every time, with the 'true' string inserted if there is a match by the 'tidy up' code. If there is no match at all then the 'else' code is inserted. The \romannumeral business means that it always requires exactly two expansions to do the work here:

\documentclass{article}
\usepackage{pdftexcmds}
\makeatletter
\newcommand*{\dothis}[1]{%
  \stringcases
    {#1}%
    {%
      {a}{so you typed a}%
      {b}{now this is b}%
      {c}{you want me to do c?}%
    }%
    {[nada]}%
}
\newcommand{\stringcases}[3]{%
  \romannumeral
    \str@case{#1}#2{#1}{#3}\q@stop
}
\newcommand{\str@case}[3]{%
  \ifnum\pdf@strcmp{\unexpanded{#1}}{\unexpanded{#2}}=\z@
    \expandafter\@firstoftwo
  \else
    \expandafter\@secondoftwo
  \fi
    {\str@case@end{#3}}
    {\str@case{#1}}%
}
\newcommand{\str@case@end}{}
\long\def\str@case@end#1#2\q@stop{\z@#1}
\makeatother

\begin{document}

\dothis{a}

\dothis{b}

\dothis{c}

\dothis{e}

\end{document}

Though it's most likely too late for the OP, I just worked out my own switch and thought I'd share it here for future readers. My solution uses solely the package xifthen (ifthen suffices too, but I already had xifthen installed...).

% Switch implementation
\usepackage{xifthen}
\newcommand{\ifequals}[3]{\ifthenelse{\equal{#1}{#2}}{#3}{}}
\newcommand{\case}[2]{#1 #2} % Dummy, so \renewcommand has something to overwrite...
\newenvironment{switch}[1]{\renewcommand{\case}{\ifequals{#1}}}{}

% Example: Pick color by ID
\newcommand{\incolor}[2]{
    \begin{switch}{#1}
        \case{1}{\color{red}}
        \case{2}{\color{blue}}
        \case{3}{\color{green}}
        \case{4}{\color{black}}
        #2
    \end{switch}
}

This code compiles perfectly fine in my TeXMaker (ofc. you'll need the color-package for this example, but it's not part of the switch). The example colors a given input in a color defined by an ID I chose (Usage: \incolor{ID}{Content}). I used it for shorthand notations of lots of things (e.g. \lp1, \lp2, ... for parentheses in different colors using \newcommand{\lp}[1]{\incolor{#1}{\langle}}). Feel free to experiment ;)

I could imagine this to be expanded to a solution using only built-in control structures, but I've been too lazy for now to do so, yet \ifx and \else should do the trick.


The following is from catoptions package. The following \ifcasse is \cptifcasse in catoptions package. I think Count Zero should simply load an existing package for his task.

\documentclass{article}
\usepackage{pdftexcmds}
\makeatletter
\long\def\am@alltoendif#1\endif{\unexpanded{#1}}
\long\def\am@domatchcode#1#2\endif{\unexpanded{#1}}
\long\def\amifcond#1\fi{\csname @#1first\else second\fi oftwo\endcsname}
\long\def\amifstrcmp#1#2{%
  \amifcond\if0\pdf@strcmp{\detokenize{#1}}{\detokenize{#2}}\fi
}
\def\ifcasse#1#2{%
  \amifstrcmp{#1}\ifnone{%
    \am@alltoendif
  }{%
    \amifstrcmp{#1}\endif{}{%
      \amifstrcmp{#2}\ifnone{%
        \am@alltoendif
      }{%
        \amifstrcmp{#2}\endif{}{\am@ifcasse{#1}{#2}}%
      }%
    }%
  }%
}
\def\am@ifcasse#1#2#3{%
  \amifstrcmp{#3}\ifnone{%
    \am@alltoendif
  }{%
    \amifstrcmp{#3}\endif{}{%
      #1{#2}{#3}\am@domatchcode{\am@ifcasse@i{#1}{#2}}%
    }%
  }%
}
\def\am@ifcasse@i#1#2#3{\am@ifcasse{#1}{#2}}

% The user can also define his own logical test command and pass it as the first 
% argument of \ifcasse. For example, we define \ifnumtest:

\def\ifnumtest#1#2{\amifcond\ifnum#1#2\fi}

% We rewrite Count Zero's macro:
\newcommand*{\dothis}[1]{%
  \par
  \ifcasse\amifstrcmp{#1}%
    {a}{so you typed a}
    {b}{now this is b}
    {c}{you want me to do c?}
  \ifnone
    [no match]%
  \endif
}
\makeatother

\begin{document}
\dothis{a}
\dothis{b}
\dothis{c}
\dothis{e}

% Weird test that correctly gives \x as 'empty':
\edef\x{%
  \ifcasse\amifstrcmp{x}
  \endif
}
%\show\x

% Weird test that gives \x as 'no match':
\edef\x{%
  \ifcasse\amifstrcmp{x}
  \ifnone
    [no match]%
  \endif
}
\par``\x''.

% Number test:
\edef\x{%
  \ifcasse\ifnumtest{2}
    {=1}{equal to 2}
    {<3}{less than 3}
    {>4}{greater than 4}
  \ifnone
    no match%
  \endif
}
\par``\x''.
\end{document}

Tags:

Conditionals