27

How can I create a command \if with 1 argument, namely #1,

\if{#1=1}{symbol1}...{#1=n}{symboln}

that returns symbol1, when #1 is 1, ..., and returns symboln, when #1 is n, and returns nothing, when #1 isn't 1,...,n?

For example, I'd like to use the command

\if{#1=1}{\mapsto}{#1=2}{\mapsfrom}{#1=3}{\rightarrow}

when I'm defining a larger command.

3
  • It's not necessary to sign your questions (as there is already a box with your username below it) or to begin them with a greeting.
    – Thorsten
    Commented May 7, 2011 at 17:08
  • @Thorsten: OK, won't greet unnecessarily anymore. However, I don't know what "sign your questions" means, I didn't sign anything.
    – Leo
    Commented May 7, 2011 at 17:28
  • Well I just took one of our text building blocks from meta.tex.stackexchange.com/q/430/3240
    – Thorsten
    Commented May 7, 2011 at 17:30

2 Answers 2

35

For simple integer comparisons, TeX provides \ifcase:

\ifcase<integer>
  % Case 0
\or
  % Case 1
\or
...
\else
  % Optional
\fi

So you can define a wrapper such as

\newcommand\myswitch[1]{%
  \ifcase#1\relax
    \ValueWasZero
  \or
    \ValueWasOne
  \or
    \ValueWasTwo
  ...
  \else
     \OtherCases
  \fi
}

Here, you start from the 0 case and work upward: often you'll see \ifcase#1\relax\or with no 0 case at all. You can use as many \or statements as you like, depending on how many numbers you need. The \else is optional, and is used if you want 'otherwise do this' functionality.

By the way, don't define \if: this is a TeX primitive which you should not change!

4
  • 1
    hmm, I don't really understand what's going on. You can assume that #1 is always an integer and assume that symbol1...symboln are latex symbols, such as "\mapsto", "\rightarrow", and so on. I was expecting \newcommand{\if}{...} as your answer. Could you give me an example of how to use the command?
    – Leo
    Commented May 7, 2011 at 16:57
  • Oh and another comment, this command "if" that I'm asking for, is primarily meant to be used when defining larger commands, so I don't have to copy paste them, since they are going to be almost identical.
    – Leo
    Commented May 7, 2011 at 17:00
  • @Leon: Does the edit help?
    – Joseph Wright
    Commented May 7, 2011 at 17:08
  • Yes, it's working! For others that might read this, my example from the original question would be witten \ifcase #1 \or \mapsto \or \mapsfrom \or \rightarrow \else \fi. For example \ifcase 2 \or \mapsto \or \mapsfrom \or \rightarrow \else \fi returns \mapsfrom. Thank you, @Joseph Wright.
    – Leo
    Commented May 7, 2011 at 17:26
16

Using \ifcase as Joseph Wright suggested is the best way most the time.

An alternative which might have benefits for some applications would be to define a set of macros which names dependent on the number. Using \csname ...\endcsname or \@namedef macro names can contain numbers or these can be converted to a Roman number using \romannumeral. Then \@nameuse can be used to use these macros. The etoolbox package also provides the identical user-level macros \csdef and \csuse.

\documentclass{article}

\makeatletter
\newcommand\defcase[1]{\@namedef{mycase@\the\numexpr#1\relax}}
\newcommand\myswitch[1]{\@nameuse{mycase@\the\numexpr#1\relax}}
\makeatother

% or alternatively:
\makeatletter
\newcommand\defcase[1]{\@namedef{mycase@\romannumeral#1}}
\newcommand\myswitch[1]{\@nameuse{mycase@\romannumeral#1}}
\makeatother

% Define cases:
\defcase{0}{code for case 0}
\defcase{1}{code for case 1}
\defcase{2}{code for case 2}
\defcase{3}{...}

\begin{document}
% Usage
\myswitch{1}
% \myswitch{some integer expression}

\end{document}

The use of the eTeX primitive \numexpr makes the whole thing a little more robust to fancy user input.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .