How to turn string into command?

The TeX primitives \csname...\endcsname allow to construct macro names.

\documentclass{article}

\usepackage{tikz}

\newcommand*{\cta}{A}
\newcommand*{\ctb}{BB}
\newcommand*{\ctc}{CCC}
\newcommand*{\ctd}{DDDD}

\begin{document}

\foreach \i in {a,b,c,d}{The content of \texttt{\expandafter\string\csname ct\i\endcsname} is \csname ct\i\endcsname.\par}

\end{document}

enter image description here

When TeX encounters

\csname ct\i\endcsname

it expands \i (and it keeps expanding) until only character tokens are obtained, and builds a control sequence with the corresponding "string". (An error is thrown if the expansion produces a non-character token.)


A fairly general loop:

documentclass{article}
\usepackage{xparse}

\ExplSyntaxOn

\NewDocumentCommand{\loopvar}{m +O{} m +O{}}
 {
  \clist_map_inline:nn { #3 } { #2 \use:c { #1##1 } #4 }
 }

\ExplSyntaxOff

\newcommand{\cta}{\texttt{\string\cta}}
\newcommand{\ctb}{\texttt{\string\ctb}}
\newcommand{\ctc}{\texttt{\string\ctc}}
\newcommand{\ctd}{\texttt{\string\ctd}}

\begin{document}

\loopvar{ct}{a,b,c,d}

\loopvar{ct}[This is ]{a,b,c}[\par]

\end{document}

The first mandatory argument is the common part, the second mandatory argument is the list of strings to append; the first optional argument is a “prefix” to add before the macro, the traling one is the “postfix”.

Explanation: \use:c builds a control sequence name from its argument and is essentially \csname...\endcsname in disguise; \clist_map_inline:nn maps the comma separated list executing for each item the code specified in the second argument (#1 stands for the current item, but here we need to use ##1 because we're defining a macro).

enter image description here


As in TeX everything is about tokens that might be expandable, you are faced with the question about the order in time in which expansion of \cta, \ctb, \ctc, \ctd shall take place.

Case 1:

Is the loop to deliver the entire token-sequence \cta\ctb\ctc\ctd ?

(In case \cta is a macro that processes three non-delimited arguments, its first argument is the token \ctb, its second argument is the token \ctc and its third argument is the token \ctd.)

Case 2:

Is the token \cta to be produced and expanded totally and carried out completely in the first iteration, then the token \ctb to be produced and expanded totally and carried out completely in the second iteration, then the token \ctc to be produced and expanded totally and carried out completely in the third iteration, then the token \ctd to be produced and expanded totally and carried out completely in the fourth iteration?

How to do the second case has already been shown by campa and egreg.

So let's focus on the first case:

You could use a scratch-macro for accumulating tokens:

\documentclass{article}

\usepackage{tikz}

\newcommand*{\cta}[3]{%
  \noindent
  \texttt{\string\cta}'s first argument is: \texttt{\string#1}\\%
  \texttt{\string\cta}'s second argument is: \texttt{\string#2}\\%
  \texttt{\string\cta}'s third argument is: \texttt{\string#3}%
  
  \bigskip

  #1#2#3%
}
\newcommand*{\ctb}[2]{%
  \noindent
  \texttt{\string\ctb}'s first argument is: \texttt{\string#1}\\%
  \texttt{\string\ctb}'s second argument is: \texttt{\string#2}%

  \bigskip

  #1#2%
}
\newcommand*{\ctc}[1]{%
  \noindent
  \texttt{\string\ctc}'s first argument is: \texttt{\string#1}%

  \bigskip

  #1%
}
\newcommand*{\ctd}{%
  \noindent
  \texttt{\string\ctd} does not process arguments.%
}

\newcommand\scratchmacro{}%

\begin{document}

\def\scratchmacro{}
\foreach \i in {a,b,c,d}{%
  \csname g@addto@macro%
           \expandafter\endcsname
           \expandafter{%
           \expandafter\scratchmacro
           \expandafter}%
           \expandafter{%
             \csname ct\i\endcsname
          }%
}%

\noindent
\texttt{\string\scratchmacro: \meaning\scratchmacro}

\bigskip

\scratchmacro

\end{document}

enter image description here

If you wish a fully expandable loop, then you are faced with the task of expandable comma-list-parsing.

In this case you might be interested in the answers to the question \newcommand with many arguments.

If you wish a fully expandable loop, but can make it with a list of non-delimited arguments instead of a comma-list, i.e., something like {a}{b}{c}{d} instead of a,b,c,d, then you are faced with the task of expandable argument-list-parsing.

In this case you might be interested in some of the answers to the question defining a new command with variable name in a loop.


Another approach could be:

\documentclass{article}

\makeatletter
\newcommand\UD@exchange[2]{#2#1}%
\newcommand\nameloop{\romannumeral0\UD@innernameloop}%
\newcommand\UD@innernameloop[3]{%
  \ifx\relax#3\expandafter\@firstoftwo\else\expandafter\@secondoftwo\fi
  { #2}{%
    \expandafter\UD@exchange
    \expandafter{%
    \expandafter{%
      \romannumeral0%
      \expandafter\UD@exchange\expandafter{%
        \csname#1#3\endcsname
      }{ #2}%
    }}{%
      \UD@innernameloop{#1}%
    }%
  }%
}%
\makeatother

\expandafter\expandafter\expandafter\def
\expandafter\expandafter\expandafter\scratchmacro
\expandafter\expandafter\expandafter{%
  \nameloop{ct}{Tokens in front}{a}{b}{c}{d}{\relax}%
}%

\begin{document}

\texttt{\string\scratchmacro: \meaning\scratchmacro}

\end{document}

enter image description here

Tags:

Macros