# How do I use IfStrEqCase within a siunitx command?

I am having trouble using \IfStrEqCase from xstring inside \num from siunitx:

\documentclass{article}
\usepackage{xstring}
\usepackage{siunitx}

\newcommand{\bla}[1]{%
\IfStrEqCase{#1}{{a}{1}%
{b}{2}%
{c}{3}}%
[0]%
}
\newcommand{\blubb}[1]{1}

\begin{document}
|\num{\blubb{a}}|
|\bla{a}|
|\num{\bla{a}}|
\end{document}


Will fail at |\num{\bla{a}}| with:

pdflatex.exe> ! TeX capacity exceeded, sorry [input stack size=5000].
pdflatex.exe> \reserved@a ->\def \reserved@a
pdflatex.exe>                                *{\let \@xs@assign\@xs@expand@and@detokenize...
pdflatex.exe> l.16 |\num{\bla{a}}
pdflatex.exe>                    |
pdflatex.exe> !  ==> Fatal error occurred, no output PDF file produced!


How can I overcome this? Solutions that do not include IfStrEqCase but provide some other way to do switch/case are welcome.

-
Could you explain what you are trying to achieve as an outcome? The \num command is meant to format 'numbers', not really 'expressions' and certainly not things that can't be expanded to numbers. You input (e.g. a) doesn't look at all like a number! –  Joseph Wright Mar 11 at 14:03
@JosephWright I am going to have the definition of \bla outsourced in an included .tex file that is automatically generated by a script in a programming language of my choice thay expands the IfStrEqCase command with all variables (eg. a,b,c) with its values(1,2,3) and an other hopfully and other IfStrEqCase with their units... (I know sweave and knitr, but working with invalid latex code is no option with my editor) –  YAK Mar 11 at 14:55

As the manual says, commands from xstring are not fully expandable and may not be nested nor used e.g. in \edef. Several of the xstring commands thus have a final optional argument which is a macro where the result may be stored. This in to the situation for \IfStrEqCase, so you need to provide something like this in the code for each case. For example:

\documentclass{article}
\usepackage{xstring}
\usepackage{siunitx}

\newcommand{\bla}[2]{%
\IfStrEqCase{#1}{{a}{\xdef#2{1}}%
{b}{\xdef#2{2}}%
{c}{\xdef#2{3}}}%
[\xdef#2{0}]%
}
\newcommand{\blubb}[1]{1}

\begin{document}
|\num{\blubb{a}}|

|\bla{a}{\outp}\outp|

|\bla{b}{\outp}\num{\outp}|
\end{document}


In this way you can define a command

\newcommand{\blanum}[1]{\bla{#1}{\outp}\num{\outp}}


that you can use directly as \blanum{b}.

-
Works like a charm, ty! I would appreciate if extended your answer for a shortcut à la \newcommand{\bla}[1]{\blahelper{#1}{\outp}\num{\outp}} to make clear it is almost as easy to use as if \IfStrEqCase was fully expandable (whatever that means). –  YAK Mar 11 at 14:41
OK, example definition added. –  Andrew Swann Mar 11 at 15:01

Here is a version using stringstrings. While the \convertchar macro cannot be nested inside of a \num argument, its result (\thestring) is expandable, and can thus be solved in a two-step, as I do in the macro \Inum (indirect \num).

EDITED to take not just letters, but words, as arguments.

\documentclass{article}
\usepackage{stringstrings}
\usepackage{siunitx}

\newcommand\Inum[1]{\bla[q]{#1}\num{\thestring}}

\newcommand{\bla}[2][v]{%
\convertword[q]{#2}{ax}{1}%
\convertword[q]{\thestring}{by}{2}%
\convertword[#1]{\thestring}{c}{3}%
}
\newcommand{\blubb}[1]{1}

\begin{document}
|\num{\blubb{a}}|
|\bla{ax}|
|\Inum{by}|
\end{document}

-
Ok. But it only works for single chars (I admit, I did not state this requirement in the question). And what is that q as first argument of bla needed for? Anyway good answer explaining this \thestring trick. –  YAK Mar 11 at 15:29
@YAK Fixed for your revised case, merely by changing \convertchar into \convertword. The [q] option is for "quiet", so that intermediate results (stored in \thestring) are not printed out. I made the default [v] verbose, so that \thestring is printed out at the end of \bla, unless invoked with a [q] (or a [e], see package documentation for details). –  Steven B. Segletes Mar 11 at 17:29
thank you for the fix and the explanation, works like a charm. –  YAK Mar 11 at 21:43