57

Suppose I want to define a command, say, \tree with, say, two arguments. I would like \tree to do different things depending on what my first argument is. For example,

if #1 = a, then return $\sqrt{#2}$

if #1 = b, then return "Hi"

Is it possible to realise the above pseudocode? If so, how can I?

lockstep
  • 250,273
JSeaton
  • 1,081

5 Answers5

50

You can also use \IfEqCase from the xstring package which can easily be extended to add more cases:

enter image description here

Notes:

  • Besides being able to easily extend to more cases, this also has the benefit that it will produce a \PackageError if an unknown option is passed in.

Code:

\documentclass{article}
\usepackage{xstring}

\newcommand{\tree}[2]{% \IfEqCase{#1}{% {a}{$\sqrt{#2}$}% {b}{Hi}% % you can add more cases here as desired }[\PackageError{tree}{Undefined option to tree: #1}{}]% }% \begin{document} \tree{a}{4}

\tree{b}{4}

%\tree{c}{4} \end{document}

Peter Grill
  • 223,288
  • What about if I need to use multiple conditions/variables for the same case, for example CASE1: if a=1 and/or b=2 : then do this and so on. Identifying multiple variables in the same case – Silva Feb 20 '20 at 21:07
  • @Silva: In general, you should be able to nest the cases, or perhaps make use of Modified \IfStrEqCase with multiple matches per case. But, without seeing more details I can't give you an exact answer. If you are unable to locate the answer on this site, I'd suggest you ask a new question and include a MWE that illustrates the problem including the \documentclass and the appropriate packages. If this question is relevant you should link to it. – Peter Grill Feb 20 '20 at 21:45
  • https://tex.stackexchange.com/questions/529341/multiple-cases-for-xstring-package – Silva Feb 20 '20 at 21:59
18

ifthen package then

  \newcommand\tree[2]{\ifthenelse{\equal{#1}{a}}{$\sqrt{#2}$}{Hi}}

actually I mis read your condition so I suppose the full version is

 \newcommand\tree[2]{\ifthenelse{\equal{#1}{a}}%
                     {$\sqrt{#2}$}{\ifthenelse{\equal{#1}{b}}{Hi}{zzz}}}

I think all the answers given so far (including mine above) are not expandable which means that you can't to the test in places like a \write or \edef see the \typeout below. Given your \sqrt example that probably doesn't matter, but the following is a version using expandable tests that is almost certainly the quickest version posted so far, although rather expensive in terms of command name use.

\documentclass{article}

\makeatletter
\@namedef{tree@a}#1{$\sqrt{#1}$}
\@namedef{tree@b}#1{h1}
\def\tree#1{\expandafter\ifx\csname tree@#1\endcsname\relax
\expandafter\@gobble\else
\csname tree@#1\expandafter\endcsname
\fi}

\makeatother


\begin{document}
\tree{a}{2}

\typeout{[[[\tree{b}{2}]]]}

\tree{b}{xyz}

\tree{x}{Uh!}

\end{document}
David Carlisle
  • 757,742
10

The easiest implementation is with expl3:

\documentclass{article}
\usepackage{xparse}
\ExplSyntaxOn
\NewDocumentCommand{\tree}{ m m }
 {
  \seaton_tree:nn { #1 } { #2 }
 }
\cs_new:Npn \seaton_tree:nn #1 #2
 {
  \str_case:nnF { #1 }
   {
    { a } { $\sqrt{ #2 }$ }
    { b } { Hi }
    % other possible strings
   }
   {
    I~don't~know~what~to~do~with~`#1'
   }
 }
\ExplSyntaxOff

\begin{document}
\tree{a}{2}

\tree{b}{xyz}

\tree{x}{Uh!}

\end{document}

The list of admissible strings can be arbitrarily long.

egreg
  • 1,121,712
7

Another variation on the theme flowing through the answers is to use the etoolbox; same idea, just different syntax.

\documentclass{article}
\usepackage{etoolbox}

\newcommand{\tree}[2]{%
    \ifstrequal{#1}{a}%
        {$\sqrt{#2}$}%
        {\ifstrequal{#1}{b}{Hi}{\PackageError{tree}{Undefined option to tree command}{}}}%
        }
\begin{document}
\tree{a}{4}

\tree{b}{4}

% this one throws an error
%\tree{c}{4}
\end{document}
cmhughes
  • 100,947
6

You don't mention what a and b are supposed to be, so I'll assume that they are character strings (possibly of unit length). The following construct, which makes use of the \ifthenelse macro of the ifthen package, should work for you:

\newcommand{\tree}[2]{%
    \ifthenelse{\equal{#1}{a}}{$\sqrt{#2}$}{%
    \ifthenelse{\equal{#1}{b}}{"Hi."}{}}}

Notice that you don't appear to specify what should be done if #1 is not equal to either a or b. I've therefore set the outcome for that case to {}.

Mico
  • 506,678