Recall arbitrary positional argument

You can build an internal command of the right form

\documentclass{article}

\def\switchtwo#1#2#3{%
\def\tmp##1##2{###3}%
\tmp{#1}{#2}}

\usepackage[T1]{fontenc}

\begin{document}

\switchtwo{aaa}{bbb}{1}

\switchtwo{\string\or}{\string\fi}{2}


\end{document}

\newcommand{\switchtwo}[3]{#(#3)}— The syntax you have in mind implies the possibility of using #⟨whatsoever⟩ for "dynamically" denoting arguments of a macro at times when that macro is expanded.

This is not possible in (La)TeX:

Only at the time of defining a macro you can use #1 and #2 etc for denoting its parameters.

Denoting one of its arguments by #⟨whatsoever⟩ at the time of expanding is not possible.

At the time of expanding, the ⟨parameter-text⟩ of a macro's definition is taken for a set of directives for one by one gathering arguments from the token-stream:
When expansion of \switchto takes place, LaTeX gathers the arguments from the token-stream: First it gathers from the token-stream that argument/that set of tokens that is denoted by the definition-text's parameter #1. Then it gathers from the token-stream that argument/that set of tokens that is denoted by the definition-text's parameter #2. Then it gathers from the token-stream that argument/that set of tokens that is denoted by the definition-text's parameter #3. Then it inserts these sets of tokens into the replacement-text which it returns to the token-stream.

What can you do in LaTeX?

David Carlisle showed in his answer how to use ##⟨whatsoever⟩ within the definition-text of a macro for "dynamically denoting" one of the arguments of another macro, a temporary macro, at the time of defining that other/temporary macro.

Approaches focused at defining temporary macros cannot be used in expansion-contexts.

Other possibilities (that can be used in expansion-contexts as well) are:

As long as it is ensured that the third argument is a ⟨number⟩ in the sense of The TeXbook—the precise meaning of the quantity ⟨number⟩ is discussed in The TeXbook, Chapter 24: Summary of vertical mode —, you can probably do something like this:

\documentclass{article}

\makeatletter
\newcommand{\switchtwo}[3]{%
  \romannumeral0\ifnum\number\number0#3=1 \expandafter\@firstoftwo\else\expandafter\@secondoftwo\fi
  {\expandafter\@firstoftwo\@secondoftwo}{%
    \ifnum\number\number0#3=2 \expandafter\@firstoftwo\else\expandafter\@secondoftwo\fi
    {\expandafter\@secondoftwo\@secondoftwo}%
    {\@firstoftwo}%
  }%
  { Error: Arg 3 is neither 1 nor 2}{{ #1}{ #2}}%
}%
\makeatother

\begin{document}

\switchtwo{A}{B}{1}

\switchtwo{A}{B}{2}

\switchtwo{A}{B}{3}

\switchtwo{A}{B}{}

\hrulefill

\newcounter{foobar}

\setcounter{foobar}{1}%
\switchtwo{A}{B}{\number\value{foobar}}

\setcounter{foobar}{2}%
\switchtwo{A}{B}{\number\value{foobar}}

\setcounter{foobar}{3}%
\switchtwo{A}{B}{\number\value{foobar}}

\end{document}

In the example above \romannumeral0... is not used for obtaining the roman-numeral-representation of a number. \romannumeral0... is used for triggering a lot of expansion-work during the search for more digits or a space-token that will be discarded as it just terminates the digit-sequence and therefore also terminates the search for more digits. It is ensured that after all this expansion-work a space-token is found, which terminates the digit-sequence 0. Therefore after all the expansion-work a non-positive number is found while \romannumeral will silently swallow non-positive numbers without returning any tokens at all.

Be aware that a reliable test whether an arbitrary token sequence in \switchtwo's third argument forms a valid ⟨number⟩ in the sense of The TeXbook is not feasible:

An arbitrary token sequence might form an arbitrary expansion-based algorithm. Therefore such a test includes testing whether the result of an arbitrary expansion-based algorithm forms a valid ⟨number⟩ in the sense of The TeXbook. This in turn implies testing whether an arbitrary expansion-based algorithm terminates at all (without error-messages). This in turn implies solving the halting problem. Alan Mathison Turing proved in 1936 that a general algorithm to solve the halting problem for all possible program-input pairs does not exist.


In case you prefer checking whether the set of tokens contained in \switchto's third argument (without whatsoever expansion/evaluation) consists either exactly of the catcode-12-(other)-character-token 1 or exactly of the catcode-12-(other)-character-token 2 or of something else, this can be done by means of delimited arguments:

\documentclass{article}

\makeatletter
%%-----------------------------------------------------------------------------
%% Check whether argument is empty:
%%.............................................................................
%% \UD@CheckWhetherNull{<Argument which is to be checked>}%
%%                     {<Tokens to be delivered in case that argument
%%                       which is to be checked is empty>}%
%%                     {<Tokens to be delivered in case that argument
%%                       which is to be checked is not empty>}%
%%
%% The gist of this macro comes from Robert R. Schneck's \ifempty-macro:
%% <https://groups.google.com/forum/#!original/comp.text.tex/kuOEIQIrElc/lUg37FmhA74J>
\newcommand\UD@CheckWhetherNull[1]{%
  \romannumeral0\expandafter\@secondoftwo\string{\expandafter
  \@secondoftwo\expandafter{\expandafter{\string#1}\expandafter
  \@secondoftwo\string}\expandafter\@firstoftwo\expandafter{\expandafter
  \@secondoftwo\string}\@firstoftwo\expandafter{} \@secondoftwo}%
  {\@firstoftwo\expandafter{} \@firstoftwo}%
}%
%%-----------------------------------------------------------------------------
%% \UD@DigitFork{<Argument which is to be checked>}%
%%              {<Tokens to be delivered in case that argument
%%                which is to be checked is formed by a set of 
%%                tokens which contains only the catcode-12-character 1>}%
%%              {<Tokens to be delivered in case that argument
%%                which is to be checked is formed by a set of 
%%                tokens which contains only the catcode-12-character 2>}%
%%              {<Tokens to be delivered in case that argument
%%                which is to be checked is formed by a set of 
%%                tokens which is empty or contains something else>}%
%%
\@ifdefinable\UD@GobbleToExclam{\long\def\UD@GobbleToExclam#1!{}}%
\@ifdefinable\UD@DigitSelect{\long\def\UD@DigitSelect#1!!1!2!#2#3!!!!{#2}}%
\newcommand\UD@DigitFork[4]{%
  \expandafter\UD@CheckWhetherNull\expandafter{\UD@GobbleToExclam#1!}{%
    \UD@DigitSelect
    !#1!1!2!{#4}% empty
    !!#1!2!{#2}% 1
    !!1!#1!{#3}% 2
    !!1!2!{#4}% something else without !
    !!!!%
  }{#4}% something else with !
}%
%%-----------------------------------------------------------------------------
%% \switchto
\newcommand\switchtwo[3]{%
  \romannumeral0\UD@DigitFork{#3}{ #1}{ #2}{ Error: Arg 3 is neither 1 nor 2}%
}%
\makeatother

\begin{document}

\switchtwo{A}{B}{1}

\switchtwo{A}{B}{2}

\switchtwo{A}{B}{3}

\switchtwo{A}{B}{}

\hrulefill

Be aware that this variant of \verb|\switchto| does not evaluate its third argument
and that the token-set \verb|\number\value{foobar}| in any case neither does
equal the token \texttt{1$_{12}$} nor does equal the token \texttt{2$_{12}$}:

\newcounter{foobar}

\setcounter{foobar}{1}%
\switchtwo{A}{B}{\number\value{foobar}}

\setcounter{foobar}{2}%
\switchtwo{A}{B}{\number\value{foobar}}

\setcounter{foobar}{3}%
\switchtwo{A}{B}{\number\value{foobar}}

\end{document}

By the way:

None of the tests presented in this answer defines temporary macros.

Therefore the tests presented in this answer are suitable for expansion-contexts also.

E.g., you can do things like \csname @\switchtwo{first}{second}{1}oftwo\endcsname{first}{second}.

With the tests presented in this answer, the placement of the first and second argument of \switchtwo is done in a way where unbalanced \csname/\endcsname/\if.../\or/\else/\fi in the arguments don't disturb.

E.g., you can do things like \csname @\switchtwo{\ifx AA}{\ifx AB}{1}first\else second\fi oftwo\endcsname{first}{second}.

But be aware that brace/group-nesting is independent from \if....\else..\fi-matching and that therefore such things can disturb the \if....\else..\fi-matching of surrounding \if....\else..\fi-constructs.


You can use \ifcase:

\newcommand{\switchtwo}[3]{%
  \ifcase#3 \or#1\or#2\fi
}

The macro will return nothing if the third argument is neither 1 nor 2, but you'll get errors or garbage if the third argument is not an integer.

Your idea can't work, because the positional arguments in a definition are stored in a special way and you can't mix the replacement text with them.