Is it possible to create a command with another command, passing code as a string?

I want to loop through a list and print some text. The placement of that text is inside a table, inside a \makecell command. I could hard-code the items from the list I want, including some \\ commands to break lines. But I don't want to hard-code, I want to use a loop. MWE:

\documentclass[]{article}
\usepackage{makecell}
\usepackage{pgffor}
\newcommand\AuthorList{First MI. Last, First MI. Last, First MI. Last}
\newcommand\PrintAuthorList{\foreach \x in \AuthorList
{
\x
}
}

\begin{document}

\begin{table*}[h]
\begin{tabular}{|l|l|}
\hline
\makecell[tl]{row 1, line 1 \\ row 1, row 2} & stuff\\
\hline
row 2, no cells & \makecell{This is where I want to print the author list, one per line:\\ \PrintAuthorList}\\
\hline
\end{tabular}
\end{table*}

\begin{table*}[h]
\begin{tabular}{|l|l|}
\hline
\makecell[tl]{row 1, line 1 \\ row 1, row 2} & stuff\\
\hline
row 2, no cells & \makecell{This is where I've hard-coded the result I want:\\ First MI. Last\\First MI. Last\\First MI. Last}\\
\hline
\end{tabular}
\end{table*}

\end{document}


That code will compile but will not break lines between author names. If I add \\ to the foreach loop, it won't even compile.

My thought is that I have one command create a string with the slashes that I want, and have that string passed as code in my \makecell environment. For example:

\newcommand{\MakeAuthorString}{\foreach \x in \AuthorList{\x\textbackslash\textbackslash}}


But passing this into the makecell environment obviously just prints the backslashes as text. I want the string to be passed somehow as code... with actual backslashes that don't evaluate until they get in the makecell environment.

• unrelated but don't use \begin{table*}[h] : table* is for tables that span two columns and does not have h it just does something here as in single node table* drops back to being table – David Carlisle Nov 1 '19 at 20:04

It's a one liner with xparse and expl3:

\documentclass[]{article}
\usepackage{makecell}
\usepackage{xparse}

\newcommand\AuthorList{First MI. Last, First MI. Last, First MI. Last}

\ExplSyntaxOn
\NewDocumentCommand\PrintAuthorList{}
{
\clist_use:Nn \AuthorList { \\ }
}
\ExplSyntaxOff

\begin{document}

\begin{tabular}{|l|l|}
\hline
\makecell[tl]{row 1, line 1 \\ row 1, row 2} & stuff\\
\hline
row 2, no cells & \makecell{Author List:\\ \PrintAuthorList}\\
\hline
\end{tabular}

\end{document}


In case you like \expandafter-orgies, you can use \foreach for accumulating table-rows in a temporary macro:

\documentclass[]{article}
\usepackage{makecell}
\usepackage{pgffor}
\newcommand\AuthorList{First MI. Last1, First MI. Last2, First MI. Last3}
\newcommand\MyTemp{}%
\newcommand\PrintAuthorList{%
\gdef\MyTemp{}%
\foreach \x in \AuthorList
{%
\ifx\MyTemp\empty\else
\expandafter\def\expandafter\MyTemp\expandafter{\MyTemp\\}%
\fi
\expandafter\expandafter\expandafter\gdef
\expandafter\expandafter\expandafter\MyTemp
\expandafter\expandafter\expandafter{%
\expandafter\MyTemp
\x}%
}%
%\show\MyTemp
\expandafter\gdef\expandafter\MyTemp\expandafter{\expandafter}\MyTemp
}%

\begin{document}

\begin{table}[h]
\begin{tabular}{|l|l|}
\hline
\makecell[tl]{row 1, line 1 \\ row 1, row 2} & stuff\\
\hline
row 2, no cells & \makecell{This is where I want to print the author list, one per line:\\ \PrintAuthorList}\\
\hline
\end{tabular}
\end{table}

\begin{table}[h]
\begin{tabular}{|l|l|}
\hline
\makecell[tl]{row 1, line 1 \\ row 1, row 2} & stuff\\
\hline
row 2, no cells & \makecell{This is where I've hard-coded the result I want:\\ First MI. Last1\\First MI. Last2\\First MI. Last3}\\
\hline
\end{tabular}
\end{table}

\end{document}


A variant without pgffor and without temporary macro—the author-names in \AuthorList must contain neither unbalanced \else/\fi nor tokens whose meaning equals the meaning of \MyListEndDenoter :

\documentclass[]{article}
\usepackage{makecell}

\newcommand\AuthorList{%
% Not a comma-list this time but a list of undelimited/brace-nested arguments:
{First MI. Last1}%
{First MI. Last2}%
{First MI. Last3}%
}%

\newcommand\PrintAuthorList{%
\expandafter\Exchange\expandafter{\AuthorList}{\AccumulateTableRowsLoop{}{}}{\MyListEndDenoter}%
}%
\makeatletter
\newcommand\AccumulateTableRowsLoop[3]{%
% #1 - Either empty or \\
% #2 - Accumulated table rows
% #3 - Element of AuthorList or \MyListEndDenoter
\ifx\MyListEndDenoter#3\expandafter\@firstoftwo\else\expandafter\@secondoftwo\fi
{#2}{\AccumulateTableRowsLoop{\\}{#2#1#3}}%
}%
\makeatother
\newcommand\Exchange[2]{#2#1}%
\newcommand\MyListEndDenoter{ItMustHaveAWeirdAndBizarreDefinitionWhichNoOtherMacroHas}%

\begin{document}

\begin{table}[h]
\begin{tabular}{|l|l|}
\hline
\makecell[tl]{row 1, line 1 \\ row 1, row 2} & stuff\\
\hline
row 2, no cells & \makecell{This is where I want to print the author list, one per line:\\ \PrintAuthorList}\\
\hline
\end{tabular}
\end{table}

\begin{table}[h]
\begin{tabular}{|l|l|}
\hline
\makecell[tl]{row 1, line 1 \\ row 1, row 2} & stuff\\
\hline
row 2, no cells & \makecell{This is where I've hard-coded the result I want:\\ First MI. Last1\\First MI. Last2\\First MI. Last3}\\
\hline
\end{tabular}
\end{table}

\end{document}