# “Extra \else” and inserted “\inaccessible” when using textbf with pgffor

I'm getting errors whenever I try to make \textbf interact with pgffor and xparse. Here's an MWE that gives ERROR: Extra \else and ERROR: Missing control sequence inserted at the end of the \coljoin invocation (the missing control sequence turns out to be \inaccessible). Using \flang in place of \textbf works as expected.

\usepackage{pgffor}

\newcommand{\coljoin}[1]{%
\let\acc\empty%
\foreach \x in #1 {%
\xdef\acc{\acc & \textbf{\x}}}%
\acc}

\newcommand{\llist}{a,b,c,d,e}
\newcommand{\flang}[1]{#1+1}

\begin{tabular}{cccccc}
\coljoin{\llist}
\end{tabular}


Does anyone have insight as to what \textbf is doing that interacts with the programming utilities?

The actual goal is to have some list of data whose changes propagate throughout the document without me having to do extra column counting etc. I'd like to bold some of the rows that would be generated in this way. I would most appreciate solutions that allow \coljoin to take an optional argument that is mapped over the data before it is joined (i.e. invoke as \coljoin[\textbf]{\llist} or \coljoin[\flang]{\llist}).

Extra attempts: I have tried using the same accumulator strategy, but with \multido and docsvlist. They both behave normally for non-bolded values and give the \inaccessible error for the bolded value.

You have to use a \protected@xdef:

The first parameter of \coljoin as defined below can be used to pass in the macro that needs to be executed for each entry. It defaults to just passing the cell data thru without any additional processing.

# References:

## Code:

\documentclass{article}

\usepackage{pgffor}

\makeatletter
\newcommand{\coljoin}[2][]{%
\let\acc\empty%
\foreach \x in #2 {%
\protected@xdef\acc{\acc & #1{\x}}}%
\acc}
\makeatother

\newcommand{\llist}{a,b,c,d,e}
\newcommand{\flang}[1]{#1+1}

\begin{document}
\begin{tabular}{cccccc}
\coljoin{\llist} \\
\coljoin[\textbf]{\llist} \\
\coljoin[\flang]{\llist}
\end{tabular}
\end{document}

• I had a related problem trying to use a \ref inside a \multirow with the nameref package loaded. This solution fixed it. – flamingpenguin Feb 25 '16 at 12:36

As Peter Grill explained, the error is in having \xdef; commands that are “robustified” don't like being inside \edef or \xdef.

However, you get a spurious first column, so you should initialize \acc to \@gobble instead of \empty.

\documentclass{article}
\usepackage{pgffor}

\makeatletter
\newcommand{\coljoin}[1]{%
\let\acc\@gobble
\foreach \x in #1 {%
\protected@xdef\acc{\acc &\textbf{\x}}}% <--- no space between & and \textbf
\acc}
\makeatother

\newcommand{\llist}{a,b,c,d,e}

\begin{document}

the explicit table''

\begin{tabular}{ccccc}
\bfseries a &
\bfseries b &
\bfseries c &
\bfseries d &
\bfseries e
\end{tabular}

some text above

\begin{tabular}{ccccc}
\coljoin{\llist}
\end{tabular}

some text below

\end{document}


With \empty instead of \@gobble you need a column more in the table preamble and the result is

A different strategy is using xparse and expl3:

\documentclass{article}
\usepackage{xparse}

\ExplSyntaxOn
\NewDocumentCommand{\coljoin}{ s m }
{
\IfBooleanTF { #1 }
{ \mdrop_coljoin:o { #2 } } % the *-variant expands once the argument
{ \mdrop_coljoin:n { #2 } }
}

\seq_new:N \l__mdrop_row_seq % this will contain row data
\cs_new_protected:Npn \mdrop_coljoin:n #1
{
\seq_clear:N \l__mdrop_row_seq
% add each item surrounded by \textbf{ and }
\clist_map_inline:nn { #1 } { \seq_put_right:Nn \l__mdrop_row_seq { \textbf{##1} } }
% deliver the items with & between them
\seq_use:Nn \l__mdrop_row_seq { & }
}

% this generates the expanding once' variant
\cs_generate_variant:Nn \mdrop_coljoin:n { o }
\ExplSyntaxOff

\newcommand{\llist}{a,b,c,d,e}

\begin{document}

\begin{tabular}{ccccc}
\coljoin*{\llist} \\
\coljoin{a,b,c,d,e}
\end{tabular}

\end{document}


Note that when a command is used in the argument to \coljoin, the *-variant has to be used. This is, in my opinion, clearer.

• I actually had \ifx\acc\empty...\else...\fi` to avoid the empty column, but removed it from the MWE after determining that the problem persisted without it. I like your solution better though. – mdrop May 28 '14 at 7:14