Ad question 1:
I was wondering if there are any clever workaround for including a number in a custom macro name?
I'm working with a platform that integrates LaTeX with a computer algebra system, and frequently have variables such as a[1], a[2] etc that I have to assign to tex commands.
Right now, the most functional solution I've found is using Roman numerals e.g. \newcommand{\ai}{a[1]}; however, for various reasons, it's not ideal.
As under normal category code régime you cannot obtain control-word-tokens \a1, \a2, etc, or \a[1], \a[2], etc directly by having TeX read and tokenize .tex-input and as correct invocation of \csname..\endcsname in combination with \expandafter sometimes seems cumbersome, I offer a macro \CsNameToCsToken which can be used for creating, e.g., the control-word-token \a1 from the character-token-sequence a1 or the control-word-token \a2 from the character-token-sequence a2, etc, or the control-word-token \a[1] from the character-token-sequence a[1] or the control-word-token \a[2] from the character-token-sequence a[2], etc.
Syntax:
\CsNameToCsToken⟨stuff not in braces⟩{⟨NameOfCs⟩}
→
⟨stuff not in braces⟩\NameOfCs
(⟨stuff not in braces⟩ may be empty.)
(Due to \romannumeral-expansion the result is obtained by triggering two expansion-steps, e.g., by having two "hits" with \expandafter.)
With such a macro you are not bound to specific definition commands:
\CsNameToCsToken{foo} → \foo .
\CsNameToCsToken\newcommand{foo} → \newcommand\foo .
\CsNameToCsToken\DeclareRobustCommand{foo} → \DeclareRobustCommand\foo .
\CsNameToCsToken\global\long\outer\def{foo} → \global\long\outer\def\foo .
\CsNameToCsToken\expandafter{foo}\bar → \expandafter\foo\bar .
\CsNameToCsToken\let{foo}=\bar → \let\foo=\bar .
\CsNameToCsToken\CsNameToCsToken\let{foo}={bar} → \CsNameToCsToken\let\foo={bar} → \let\foo=\bar .
\CsNameToCsToken\string{foo} → \string\foo .
\CsNameToCsToken\meaning{foo} → \meaning\foo .
\CsNameToCsToken\NewDocumentCommand{foo}... → \NewDocumentCommand\foo... .
\makeatletter
%%===============================================================================
%% End \romannumeral-driven expansion safely:
%%===============================================================================
\@ifdefinable\UD@stopromannumeral{\chardef\UD@stopromannumeral=`\^^00}%
%%===============================================================================
%% Obtain control sequence token from name of control sequence token:
%%===============================================================================
%% \CsNameToCsToken<stuff not in braces>{NameOfCs}
%% -> <stuff not in braces>\NameOfCs
%% (<stuff not in braces> may be empty.)
\@ifdefinable\CsNameToCsToken{%
\long\def\CsNameToCsToken#1#{\romannumeral\InnerCsNameToCsToken{#1}}%
}%
\newcommand\InnerCsNameToCsToken[2]{%
\expandafter\UD@exchange\expandafter{\csname#2\endcsname}{\UD@stopromannumeral#1}%
}%
\newcommand\UD@exchange[2]{#2#1}%
\makeatother
\documentclass{article}
\begin{document}
\begin{verbatim}
Define \A[1]:
\CsNameToCsToken\newcommand*{A[1]}{%
This is the replacement-text of the command whose name is \texttt{A[1]}.%
}
\end{verbatim}
\CsNameToCsToken\newcommand*{A[1]}{%
This is the replacement-text of the command whose name is \texttt{A[1]}.%
}
\begin{verbatim}
Define \A[2]:
\CsNameToCsToken\newcommand*{A[2]}{%
This is the replacement-text of the command whose name is \texttt{A[2]}.%
}
\end{verbatim}
\CsNameToCsToken\newcommand*{A[2]}{%
This is the replacement-text of the command whose name is \texttt{A[2]}.%
}
\begin{verbatim}
Using \A[1]: \CsNameToCsToken{A[1]}
\end{verbatim}
\CsNameToCsToken{A[1]}
\begin{verbatim}
Using \A[2]: \CsNameToCsToken{A[2]}
\end{verbatim}
\CsNameToCsToken{A[2]}
\end{document}

Ad question 2:
Is it possible to define a custom macro whose output is different for different inputs?
There are many more possibilities of how varying output/forking can be done depending on the tokens that make up a macro argument. I list six of them.
Possibility 1: See, e.g., the \ref-command. Its output varies depending on the input/argument. Using the package zref you can define your own class of referencing-labels which are used for assigning a value to a named constant and your own class of referencing-commands for retrieving these values. Advantage: Within the second compilation with LaTeX all variables' values are available throughout the entire compilation, not just from the moment on when they were defiined. Disadvantage: You need at least two LaTeX-runs for things to match out.
\errorcontextlines=10000
\RequirePackage{xparse}
\documentclass{article}
\usepackage{zref}
\makeatletter
@ifdefinable@zrefpropdefined{%
\ZREF@Robust\def@zrefpropdefined{%
\zref@wrapper@babel@ZREFpropdefined
}%
}%
@ifdefinable@ZREFpropdefined{%
\def@ZREFpropdefined#1#2#3#4{%
% #1 - label
% #2 - property
% #3 - tokens in case label and property are available
% #4 - tokens in case label undefined or property not available
\zref@ifrefundefined{#1}{%
\zref@refused{#1}#4%
}{%
\zref@ifrefcontainsprop{#1}{#2}{#3}{%
\protect\G@refundefinedtrue
@latex@warning{%
Missing property #2' in reference#1' on page \thepage
}%
#4%
}%
}%
}%
}%
\zref@newprop{ValueOfVariable}{\nfss@text{\reset@font\bfseries??}}%
\NewDocumentCommand\IntroduceNewVariable{mm}{%
@bsphack
\zref@wrapper@immediate{%
\zref@setcurrent{ValueOfVariable}{#2}%
\zref@labelbyprops{#1}{ValueOfVariable}%
}%
@esphack
}%
\NewDocumentCommand\RetrieveValueOfVariable{m}{%
\zref@extractdefault{#1}{ValueOfVariable}{%
@zrefpropdefined{#1}{ValueOfVariable}{%
\protect\G@refundefinedtrue
@latex@warning{%
Unspecified problem/error related to reference `#1' on page \thepage
}%
}{}%
\nfss@text{\reset@font\bfseries??}%
}%
}%
\makeatother
\begin{document}
Retrieving the value of Variable \texttt{A[1]} yields:
\RetrieveValueOfVariable{A[1]}
Retrieving the value of Variable \texttt{A[2]} yields:
\RetrieveValueOfVariable{A[2]}
\IntroduceNewVariable{A[1]}{Value of variable \texttt{A[1]}.}%
Some Text
\IntroduceNewVariable{A[2]}{Value of variable \texttt{A[2]}.}%
Retrieving the value of Variable \texttt{A[1]} yields:
\RetrieveValueOfVariable{A[1]}
Retrieving the value of Variable \texttt{A[2]} yields:
\RetrieveValueOfVariable{A[2]}
\end{document}

Possibility 2: If you don't mind coping with the oddities of the package pgfkeys, which is a component of TikZ/pgf, you can implement an interface for parsing a comma-list where
- items without
= denote names of variables whose values are to be retrieved and
- items with
= denote assigning the variable whose name is at the left of = a value consisting of the tokens at the right of the =.
PutTokens is a special key: It does denote neither variable-assignment, nor retrieval of variables. The tokens forming its value are just placed into the token-queue.
Be aware that pgfkeys removes spaces that surround key and/or value no matter if key/value is between braces. (Braces might be needed for masking commas that shall not separate elements of the comma-list but shall be part of values or the names of keys. Braces might be needed for masking = that shall not separate keys from values but shall be part of values or the names of keys.)
%\errorcontextlines=10000
\documentclass{article}
\usepackage{pgfkeys}
\makeatletter
\newcommand\ValueOfUndefinedVariable[1]{%
\GenericError{\space\@spaces\@spaces}{%
Error: Variable `#1` undefined\on@line
}{}{%
\string\Variable{<variable's name>=<tokens denoting variable's value>}%
\MessageBreak defines variables.%
}%
\nfss@text{\reset@font\bfseries??}%
}%
\@ifdefinable\@gobbletopgfkeysnovalue{%
\long\def\@gobbletopgfkeysnovalue#1\pgfkeysnovalue{}%
}%
\@ifdefinable\@keeptopgfkeysnovalue{%
\long\def\@keeptopgfkeysnovalue#1\pgfkeysnovalue{#1}%
}%
\newcommand\CheckWhetherPgfkeysnovalue[1]{%
\ifcat$\detokenize\expandafter{\@gobbletopgfkeysnovalue#1\pgfkeysnovalue}$%
\expandafter\@secondoftwo\else\expandafter\@firstoftwo\fi
{%
\ifcat$\detokenize\expandafter\expandafter\expandafter{%
\@keeptopgfkeysnovalue\@firstofone{}#1%
}$%
\expandafter\@firstoftwo\else\expandafter\@secondoftwo\fi
}{\@secondoftwo}%
}%
\makeatother
\newcommand\MyVariablesHandle[2]{%
% #1 name of variable
% #2 value of variable
\CheckWhetherPgfkeysnovalue{#2}{%
\pgfkeys{/MyVariables/#1/.initial={\ValueOfUndefinedVariable{#1}},
/MyVariables/#1%
}%
}{%
\pgfkeys{/MyVariables/#1/.initial={#2}}%
}%
}%
\pgfkeys{%
/MyVariables/.unknown/.code={%
\expandafter\MyVariablesHandle\expandafter{\pgfkeyscurrentname}{#1}%
},
/MyVariables/PutTokens/.code={#1},
/MyVariables/PutTokens/.value required,
}%
\newcommand\Variables[1]{\pgfkeys{/MyVariables/.cd,#1}}
\begin{document}
% Define variables A[1] and A[2]
\Variables{%
A[1]={Value of variable \texttt{A[1]}},
A[2]={Value of variable \texttt{A[2]}},
}%
\Variables{%
% Deliver values of variables A[1] and A[2]
PutTokens={\noindent Retrieving the value of Variable \texttt{A[1]} yields:\space },
A[1],
PutTokens={.\Retrieving the value of Variable \texttt{A[2]} yields:\space },
A[2],
% Define variables A[3] and A[4]
A[3]={Value of variable \texttt{A[3]}},
A[4]={Value of variable \texttt{A[4]}},
% Deliver values of A[3] and A[4]
PutTokens={.\Retrieving the value of Variable \texttt{A[3]} yields:\space },
A[3],
PutTokens={.\Retrieving the value of Variable \texttt{A[4]} yields:\space },
A[4],
PutTokens={.},
}%
\bigskip
% Deliver values of variables A[1] and A[2] and [A3] and [A4]
\Variables{%
% Print variables A[1] and A[2] and [A3] and [A4]
PutTokens={\noindent Retrieving the value of Variable \texttt{A[1]} yields:\space },
A[1],
PutTokens={.\Retrieving the value of Variable \texttt{A[2]} yields:\space },
A[2],
PutTokens={.\Retrieving the value of Variable \texttt{A[3]} yields:\space },
A[3],
PutTokens={.\Retrieving the value of Variable \texttt{A[4]} yields:\space },
A[4],
PutTokens={.},%
}%
\bigskip
% Deliver values of variables A[1] and A[2] and [A3] and [A4]
\noindent Retrieving the value of Variable \texttt{A[1]} yields: \Variables{A[1]}.
\Retrieving the value of Variable \texttt{A[2]} yields: \Variables{A[2]}.
\Retrieving the value of Variable \texttt{A[3]} yields: \Variables{A[3]}.
\Retrieving the value of Variable \texttt{A[4]} yields: \Variables{A[4]}.
\end{document}

Possibility 3: You say you work with a platform that integrates LaTeX with a computer algebra system.
I don't know how the computer algebra system delivers the variables to LaTeX.
Probably an approach using a .csv-file and the package datatool might be of interest.
With the following approach a database-file variables.csv is created.
From that a database is created via \DTLloaddb.
That database is iterated each time the value of a vriable is to be retrieved.
This is rather inefficient.
It is relied on NameOfVariable forming a primary key of the database.
\errorcontextlines=10000
%=====Let LaTeX create a .csv-file holding a database of names and ========
% values of named constants.
% This could as well be done via export to .csv-file by whatsoever
% other program.
\begin{filecontents}{variables.csv}
PrimaryKey,NameOfVariable,ValueOfVariable
1,A[1],Value of variable \texttt{A[1]}.
2,A[2],Value of variable \texttt{A[2]}.
3,A[3],Value of variable \texttt{A[3]}.
4,A[4],Value of variable \texttt{A[4]}.
\end{filecontents}
%==========================================================================
\documentclass{article}
\usepackage{datatool}% For loading and iterating databases; internally loads the package ifthen
\makeatletter
\newcommand\ValueOfUndefinedVariable[1]{%
\GenericError{\space@spaces@spaces}{%
Error: Variable #1 undefined\on@line
}{}{%
\string\Variable{<variable's name>=<tokens denoting variable's value>}%
\MessageBreak defines variables.%
}%
\nfss@text{\reset@font\bfseries??}%
}%
\newif\ifvariabledefined
\newcommand\RetrieveValueOfVariable[2]{%
\global\variabledefinedfalse
\DTLforeach*[{\equal{#1}{\NameOfVariable}}]{variables}{%
\PrimaryKey=PrimaryKey,%
\NameOfVariable=NameOfVariable,%
\ValueOfVariable=ValueOfVariable%
}{%
\dtlbreak
\global\variabledefinedtrue
\ValueOfVariable
}%
\ifvariabledefined\expandafter@gobble\else\expandafter@firstofone\fi
{#2}%
}%
\makeatother
\DTLloaddb{variables}{variables.csv}
\begin{document}
Retrieving the value of Variable \texttt{A[1]} yields:
\RetrieveValueOfVariable{A[1]}{\ValueOfUndefinedVariable{A[1]}}
Retrieving the value of Variable \texttt{A[2]} yields:
\RetrieveValueOfVariable{A[2]}{\ValueOfUndefinedVariable{A[2]}}
Retrieving the value of Variable \texttt{A[3]} yields:
\RetrieveValueOfVariable{A[3]}{\ValueOfUndefinedVariable{A[3]}}
Retrieving the value of Variable \texttt{A[4]} yields:
\RetrieveValueOfVariable{A[4]}{\ValueOfUndefinedVariable{A[4]}}
\end{document}

Of course you can combine this with \CsnameToCsToken for defining a macro for each variable.
This way you don't have to iterate the database each time when retrieving the value of a variable.
\errorcontextlines=10000
%=====Let LaTeX create a .csv-file holding a database of names and ========
% values of named constants.
% This could as well be done via export to .csv-file by whatsoever
% other program.
\begin{filecontents}{variables.csv}
PrimaryKey,NameOfVariable,ValueOfVariable
1,A[1],Value of variable \texttt{A[1]}.
2,A[2],Value of variable \texttt{A[2]}.
3,A[3],Value of variable \texttt{A[3]}.
4,A[4],Value of variable \texttt{A[4]}.
\end{filecontents}
%==========================================================================
\documentclass{article}
\usepackage{datatool}% For loading and iterating databases; internally loads
% the package ifthen
\makeatletter
%%===============================================================================
%% End \romannumeral-driven expansion safely:
%%===============================================================================
@ifdefinable\UD@stopromannumeral{\chardef\UD@stopromannumeral=\^^00}% %%=============================================================================== %% Obtain control sequence token from name of control sequence token: %%=============================================================================== %% \CsNameToCsToken<stuff not in braces>{NameOfCs} %% -> <stuff not in braces>\NameOfCs %% (<stuff not in braces> may be empty.) \@ifdefinable\CsNameToCsToken{% \long\def\CsNameToCsToken#1#{\romannumeral\InnerCsNameToCsToken{#1}}% }% \newcommand\InnerCsNameToCsToken[2]{% \expandafter\UD@exchange\expandafter{\csname#2\endcsname}{\UD@stopromannumeral#1}% }% \newcommand\UD@exchange[2]{#2#1}% %%=============================================================================== \newcommand\ValueOfUndefinedVariable[1]{% \GenericError{\space\@spaces\@spaces}{% Error: Variable#1` undefined\on@line
}{}{%
\string\Variable{<variable's name>=<tokens denoting variable's value>}%
\MessageBreak defines variables.%
}%
\nfss@text{\reset@font\bfseries??}%
}%
%%===============================================================================
\newcommand\RetrieveValueOfVariable[2]{%
@ifundefined{Variable@#1}{#2}{\CsNameToCsToken{Variable@#1}}%
}%
\makeatother
\DTLloaddb{variables}{variables.csv}
\DTLforeach{variables}{%
\PrimaryKey=PrimaryKey,%
\NameOfVariable=NameOfVariable,%
\ValueOfVariable=ValueOfVariable%
}{%
\csname UD@exchange\expandafter\endcsname\expandafter{\expandafter{\ValueOfVariable}}{%
\CsNameToCsToken\newcommand{Variable@\NameOfVariable}%
}%
\CsNameToCsToken\CsNameToCsToken\global\let{Variable@\NameOfVariable}{Variable@\NameOfVariable}%
}%
\begin{document}
Retrieving the value of Variable \texttt{A[1]} yields:
\RetrieveValueOfVariable{A[1]}{\ValueOfUndefinedVariable{A[1]}}
Retrieving the value of Variable \texttt{A[2]} yields:
\RetrieveValueOfVariable{A[2]}{\ValueOfUndefinedVariable{A[2]}}
Retrieving the value of Variable \texttt{A[3]} yields:
\RetrieveValueOfVariable{A[3]}{\ValueOfUndefinedVariable{A[3]}}
Retrieving the value of Variable \texttt{A[4]} yields:
\RetrieveValueOfVariable{A[4]}{\ValueOfUndefinedVariable{A[4]}}
\end{document}

Possibility 4: You can use an expl3-property-list—properties are variables, values of properties are values of variables:
\errorcontextlines=10000
\documentclass{article}
\RequirePackage{xparse}
\ExplSyntaxOn
\prop_new:c {Variables}
\NewDocumentCommand\RetrieveValueOfVariable{mm}{
% #1 = Name of variable
% #2 = tokens in case variable is not defined
\prop_if_in:cnTF {Variables} {#1}
{ \prop_item:cn {Variables} {#1} }
{ #2 }
}
\NewDocumentCommand\SetVariables{m}{
\keyval_parse:NNn \__MYSetvariable:n \__MYSetvariable:nn {#1}
}
\cs_new:Nn \__MYSetvariable:n {\__MYSetvariable:nn {#1}{}}
\cs_new:Nn \__MYSetvariable:nn {
\prop_put:cnn {Variables} {#1} {#2}
}
\ExplSyntaxOff
\makeatletter
\NewDocumentCommand\ValueOfUndefinedVariable{}{\nfss@text{\reset@font\bfseries??}}%
\makeatother
\SetVariables{%
A[1]={Value of variable \texttt{A[1]}.},
A[2]={Value of variable \texttt{A[2]}.},
}%
\SetVariables{%
A[3]={Value of variable \texttt{A[3]}.},
A[4]={Value of variable \texttt{A[4]}.},
}%
\begin{document}
Retrieving the value of Variable \texttt{A[1]} yields:
\RetrieveValueOfVariable{A[1]}{\ValueOfUndefinedVariable}
Retrieving the value of Variable \texttt{A[2]} yields:
\RetrieveValueOfVariable{A[2]}{\ValueOfUndefinedVariable}
Retrieving the value of Variable \texttt{A[3]} yields:
\RetrieveValueOfVariable{A[3]}{\ValueOfUndefinedVariable}
Retrieving the value of Variable \texttt{A[4]} yields:
\RetrieveValueOfVariable{A[4]}{\ValueOfUndefinedVariable}
\end{document}

Possibility 5: Use delimited arguments for forking. This is cumbersome and of limited use and funny because you set the value of variables within the definition-text of the two macros used for retrieving the values:
\errorcontextlines=10000
\documentclass{article}
\makeatletter
\newcommand\ValueOfUndefinedVariable{\nfss@text{\reset@font\bfseries??}}%
\@ifdefinable\gobbletoexclam{\long\def\gobbletoexclam#1!{}}%
\newcommand\RetrieveValueOfVariable[2]{%
\ifcat$\detokenize\expandafter{\gobbletoexclam#1!}$%
\expandafter\@firstoftwo\else\expandafter\@secondoftwo\fi
{%
\VariableSelectionFork
!#1!A[2]!A[3]!A[4]!{Value of variable \texttt{A[1]}.}%
!A[1]!#1!A[3]!A[4]!{Value of variable \texttt{A[2]}.}%
!A[1]!A[2]!#1!A[4]!{Value of variable \texttt{A[3]}.}%
!A[1]!A[2]!A[3]!#1!{Value of variable \texttt{A[4]}.}%
!A[1]!A[2]!A[3]!A[4]!{#2}!!!!%
}{#2}%
}%
\@ifdefinable\VariableSelectionFork{%
\long\def\VariableSelectionFork#1!A[1]!A[2]!A[3]!A[4]!#2#3!!!!{#2}%
}%
\makeatother
\begin{document}
Retrieving the value of Variable \texttt{A[1]} yields:
\RetrieveValueOfVariable{A[1]}{\ValueOfUndefinedVariable}
Retrieving the value of Variable \texttt{A[2]} yields:
\RetrieveValueOfVariable{A[2]}{\ValueOfUndefinedVariable}
Retrieving the value of Variable \texttt{A[3]} yields:
\RetrieveValueOfVariable{A[3]}{\ValueOfUndefinedVariable}
Retrieving the value of Variable \texttt{A[4]} yields:
\RetrieveValueOfVariable{A[4]}{\ValueOfUndefinedVariable}
\end{document}

Possibility 6: In case the names of your variables denote a consecutive numbering, another approach could be extracting the k-th argument of a list of arguments whose elements denote the values of variables:
\errorcontextlines=10000
\documentclass{article}
\makeatletter
%% Code for \ExtractKthArg
%%=============================================================================
%% Paraphernalia:
%% \UD@firstoftwo, \UD@secondoftwo, \UD@PassFirstToSecond, \UD@Exchange,
%% \UD@stopromannumeral, \UD@CheckWhetherNull
%%=============================================================================
\newcommand\UD@firstoftwo[2]{#1}%
\newcommand\UD@secondoftwo[2]{#2}%
\newcommand\UD@PassFirstToSecond[2]{#2{#1}}%
\newcommand\UD@Exchange[2]{#2#1}%
@ifdefinable\UD@stopromannumeral{\chardef\UD@stopromannumeral=`^^00}%
%%-----------------------------------------------------------------------------
%% 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]{%
\romannumeral\expandafter\UD@secondoftwo\string{\expandafter
\UD@secondoftwo\expandafter{\expandafter{\string#1}\expandafter
\UD@secondoftwo\string}\expandafter\UD@firstoftwo\expandafter{\expandafter
\UD@secondoftwo\string}\expandafter\UD@stopromannumeral\UD@secondoftwo}{%
\expandafter\UD@stopromannumeral\UD@firstoftwo}%
}%
%%=============================================================================
%% Extract K-th inner undelimited argument:
%%
%% \ExtractKthArg{<integer K>}%
%% {<tokens in case list of undelimited args doesn't have a k-th argumnent>}%
%% {<list of undelimited args>} %
%%
%% In case there is no K-th argument in <list of indelimited args> :
%% Does deliver <tokens in case list of undelimited args doesn't have a k-th argumnent.
%% In case there is a K-th argument in <list of indelimited args> :
%% Does deliver that K-th argument with one level of braces removed.
%%
%% Examples:
%%
%% \ExtractKthArg{0}{not available}{ABCDE} yields: not available
%%
%% \ExtractKthArg{3}{not available}{ABCDE} yields: C
%%
%% \ExtractKthArg{3}{not available}{AB{CD}E} yields: CD
%%
%% \ExtractKthArg{4}{not available}{{001}{002}{003}{004}{005}} yields: 004
%%
%% \ExtractKthArg{6}{not available}{{001}{002}{003}} yields: not available
%%
%%=============================================================================
\newcommand\ExtractKthArg[2]{%
\romannumeral%
% #1: <integer number K>
% #2: <action if there is no K-th argument>
\expandafter\UD@ExtractKthArgCheck
\expandafter{\romannumeral\number\number#1 000}{#2}%
}%
\newcommand\UD@ExtractKthArgCheck[3]{%
\UD@CheckWhetherNull{#1}{\UD@stopromannumeral#2}{% empty
\expandafter\UD@ExtractKthArgLoop\expandafter{\UD@firstoftwo{}#1}{#2}{#3}%
}%
}%
\begingroup
\def\UD@ExtractFirstArgLoop#1{%
\endgroup
@ifdefinable\UD@RemoveTillFrozenrelax{%
\long\def\UD@RemoveTillFrozenrelax##1##2#1{{##1}}%
}%
\newcommand\UD@ExtractKthArgLoop[3]{%
\expandafter\UD@CheckWhetherNull\expandafter{\UD@firstoftwo##3{}.}{\UD@stopromannumeral##2}{%
\UD@CheckWhetherNull{##1}{%
\UD@ExtractFirstArgLoop{##3#1}%
}{%
\expandafter\UD@PassFirstToSecond\expandafter{\UD@firstoftwo{}##3}%
{\expandafter\UD@ExtractKthArgLoop\expandafter{\UD@firstoftwo{}##1}{##2}}%
}%
}%
}%
}%
\expandafter\expandafter\expandafter\UD@ExtractFirstArgLoop
\expandafter\expandafter\expandafter{%
\expandafter\expandafter\ifnum0=0\fi}%
%% Usage of frozen-\relax as delimiter is for speeding things up by reducing the
%% amount of iterations needed. I chose frozen-\relax because David Carlisle
%% pointed out in <https://tex.stackexchange.com/a/578877>
%% that frozen-\relax cannot be (re)defined in terms of \outer and cannot be
%% affected by \uppercase/\lowercase.
%%
%% \UD@ExtractFirstArg's argument may contain frozen-\relax:
%% The only effect is that internally more iterations are needed for
%% obtaining the result.
\newcommand\UD@ExtractFirstArgLoop[1]{%
\expandafter\UD@CheckWhetherNull\expandafter{\UD@firstoftwo{}#1}%
{\expandafter\UD@stopromannumeral\UD@firstoftwo#1{}}%
{\expandafter\UD@ExtractFirstArgLoop\expandafter{\UD@RemoveTillFrozenrelax#1}}%
}%
%%=============================================================================
%% End of code for \ExtractKthArg.
\newcommand\ValueOfUndefinedVariable{\nfss@text{\reset@font\bfseries??}}%
\newcommand\RetrieveVariableIndex[3]{%
@ifundefined{Variables#1}{#3}{%
\expandafter\expandafter\expandafter\UD@PassFirstToSecond
\expandafter\expandafter\expandafter{\csname Variables#1\endcsname}{%
\ExtractKthArg{#2}{#3}%
}%
}%
}%
\makeatother
\newcommand\VariablesA{%
{Value of variable \texttt{A$_1$}.}%
{Value of variable \texttt{A$_2$}.}%
{Value of variable \texttt{A$_3$}.}%
{Value of variable \texttt{A$_4$}.}%
}%
\newcommand\VariablesB{%
{Value of variable \texttt{B$_1$}.}%
{Value of variable \texttt{B$_2$}.}%
{Value of variable \texttt{B$_3$}.}%
{Value of variable \texttt{B$_4$}.}%
}%
\begin{document}
Extacting the value of variable \texttt{A$_1$} yields: \RetrieveVariableIndex{A}{1}{\ValueOfUndefinedVariable}
Extacting the value of variable \texttt{A$_2$} yields: \RetrieveVariableIndex{A}{2}{\ValueOfUndefinedVariable}
Extacting the value of variable \texttt{A$_3$} yields: \RetrieveVariableIndex{A}{3}{\ValueOfUndefinedVariable}
Extacting the value of variable \texttt{A$_4$} yields: \RetrieveVariableIndex{A}{4}{\ValueOfUndefinedVariable}
Extacting the value of variable \texttt{B$_1$} yields: \RetrieveVariableIndex{B}{1}{\ValueOfUndefinedVariable}
Extacting the value of variable \texttt{B$_2$} yields: \RetrieveVariableIndex{B}{2}{\ValueOfUndefinedVariable}
Extacting the value of variable \texttt{B$_3$} yields: \RetrieveVariableIndex{B}{3}{\ValueOfUndefinedVariable}
Extacting the value of variable \texttt{B$_4$} yields: \RetrieveVariableIndex{B}{4}{\ValueOfUndefinedVariable}
\end{document}
