# Assign value to a local variable in a newcommand

I have a tex file with some of my own custom functions, one of which is a switch case function.
Because I use \input to call this file from other documents, I need the output variable to be local. However, I need a local variable to store the output while I iterate through the rest of the loop. Either that or abort the loop and go to the end of the function.

I am using tex maker and pdftex

\usepackage{xparse}
\usepackage{fp}
\usepackage{xstring}
\usepackage{ifthen}
\usepackage{printlen}
\usepackage{listofitems}
\usepackage{forloop}
\usepackage{pgffor}

\NewDocumentCommand\SwitchCase{m m}
{
\setsepchar{,/-}
\def\out{}
\foreach \ct in {1,...,\CaseCount}
{
\ifthenelse{\equal{#1}{\Cases[\ct ,1]}}
{
\def\tmp{\Cases[\ct, 2]}
%\tmp
\def\out{\tmp}
}
{}
}
\out
}

%below is a sample of how this code would work
%not exactly how I would use it, but still valid example

\begin{document}

\SwitchCase{hello}{hel-1,he-2,hello-3,Hello-4}

\end{document}


Given the example, the function should return 3, however when I attempt to set the output variable in the loop, it returns either 0 or nothing.

This function has many possible uses in my documents therefore it has to be vague.

p.s. I apologize if any of the wording is awkward, I am not the best with syntax and word choice.

• \foreach starts a group. So the local value of \out gets "forgotten". Either use \xdef\out{\tmp} (or \gdef\out{\tmp}) or use an ordinary \loop or another loop that does not use groups (you load more than enough packages for that;-). – user194703 Dec 9 '19 at 16:58
• you are using a wild collection of different idioms, expl3, pgf for the loop ifthen for the conditional, fp for the arithmetic and tex primitive def!!! You are also missing a lot of % from ends of lines it would be simpler to write it just using expl3, however the main issue is that each iteration of a pgf loop is in a group so your \def do not survive, you could use gdef (or perhaps \xdef depending on what you want the code to do) but netter not to use a loop that groups the items. – David Carlisle Dec 9 '19 at 17:00

You can implement the functionality wthout using all the packages here:

\documentclass{article}

\makeatletter
\newcommand\SwitchCase[2]{%
\def\tmpa{#1}%
\@for\tmp:=#2\do{\expandafter\zz@switch\tmp\zz@switch}%
}
\def\zz@switch#1-#2\zz@switch{%
\def\tmpb{#1}%
\ifx\tmpa\tmpb#2\fi}

\makeatother

\begin{document}

\SwitchCase{hello}{hel-1,he-2,hello-3,Hello-4}

\end{document}

• This is perfect. And it also works for delegating other functions. I have cases in which I have to load images, and it is easier to keep them all together, and therefore using the switch case helps significantly. – cdickstein Dec 9 '19 at 20:18

It's the usual problem: \foreach cycles are done in a group.

Also, you have to fully expand the replacement text of \tmp (but you don't need it and can define directly \out).

\documentclass{article}
\usepackage{xparse}
\usepackage{fp}
\usepackage{xstring}
\usepackage{ifthen}
\usepackage{printlen}
\usepackage{listofitems}
\usepackage{forloop}
\usepackage{pgffor}

\NewDocumentCommand\SwitchCase{m m}
{%
\setsepchar{,/-}%
\foreach \ct in {1,...,\Caseslen}
{%
\ifthenelse{\equal{#1}{\Cases[\ct ,1]}}
{%
\xdef\out{\Cases[\ct, 2]}
}
{}%
}%
\out
}

\begin{document}

\SwitchCase{hello}{hel-1,he-2,hello-3,Hello-4}

\end{document}


This outputs 3.

Beware of unprotected end-of-lines that generate spaces that might not be ignored, depending on the context where the macro is called.

A shorter version using expl3:

\documentclass{article}
\usepackage{xparse}

\ExplSyntaxOn
\NewDocumentCommand\SwitchCase{m m}
{
\clist_map_inline:nn { #2 }
{
\__cdickstein_switchcase_item:nn { #1 } { ##1 }
}
}

\cs_new:Nn \__cdickstein_switchcase_item:nn
{
\__cdickstein_switchcase_item:nw { #1 } #2 \q_stop
}

\cs_new:Npn \__cdickstein_switchcase_item:nw #1 #2 - #3 \q_stop
{
\str_if_eq:nnT { #1 } { #2 } { \clist_map_break:n { #3 } }
}
\ExplSyntaxOff

\begin{document}

\SwitchCase{hello}{hel-1,he-2,hello-3,Hello-4}

\end{document}


This stops at the first match.

An expandable version that again stops at the first match.

\documentclass{article}
\usepackage{xparse}

\ExplSyntaxOn
\NewExpandableDocumentCommand\SwitchCase{m m}
{
\__cdickstein_switchcase:nw { #1 } #2 , , \q_nil
}

\cs_new:Npn \__cdickstein_switchcase:nw #1 #2 ,
{
\tl_if_blank:nTF { #2 }
{
\use_none:n
}
{
\__cdickstein_switchcase_item:nw { #1 } #2 \q_stop
\__cdickstein_switchcase:nw { #1 }
}
}
\cs_new:Npn \__cdickstein_switchcase_item:nw #1 #2 - #3 \q_stop
{
\str_if_eq:nnT { #1 } { #2 } { #3 \__cdickstein_swithcase_break:w }
}

\cs_new:Npn \__cdickstein_swithcase_break:w #1 \q_nil {}
\ExplSyntaxOff

\begin{document}

\SwitchCase{hello}{hel-1,he-2,hello-3,Hello-4}

\SwitchCase{x}{x-1,y-2,x-3}

\end{document}

• I've left an opening for you to do an expandable expl3 version:-) – David Carlisle Dec 9 '19 at 17:34
• @DavidCarlisle Toobad, I got the green tick. – egreg Dec 9 '19 at 20:07