add tag
samcarter
I am trying to sequentially add elements to lists, which have the format `{word}{word}{word}` (they are ultimately for a pgf random list, which requires this format).

In the simplified example below, elements are either added to `\lista` or `\listb`, depending on the optional argument of the `\ini` macro.

Currently, I'm testing if the argument is either `a` or `b` and then add the element to the list using the hard coded name of the list:

```
\documentclass{article}

\def\lista{}
\def\listb{}
\def\atext{a}
\def\btext{b}

\ExplSyntaxOn
\NewDocumentCommand{\ini}{om}{
  \def\tmp{#1}
  \ifx\atext\tmp
    \tl_put_right:Nn \lista { {#2} }
  \fi
  \ifx\btext\tmp
    \tl_put_right:Nn \listb { {#2} }
  \fi  
}
\ExplSyntaxOff

\ini[a]{tophat}
\ini[b]{book}
\ini[b]{signpost}

\begin{document}

\lista

\listb

\end{document}
```


I'm wondering if there isn't an easier way in which the list name can be generated from the optional argument?

I tried some approaches with `\csname ...\endcsname` and friends, but run into errors like

```
! File ended while scanning text of \__kernel_exp_not:w.
<inserted text> 
                }
<*> document.tex
```


Top Answer
frougon
You can simply use `\tl_put_right:cn`. The second argument, of type `n`, is a “normal”, braced-enclosed argument; so it is not subjet to any special treatment. The first argument, of type `c`, is subject to `\csname ... \endcsname` before being passed to the base form `\tl_put_right:Nn`, which is precisely what you want. So, you only need this:

```
\NewDocumentCommand { \ini } { O{a} m }
  {
    \tl_put_right:cn { list#1 } { {#2} }
  }
```

Not sure if you really want the first argument of `\ini` to be optional; in any case, it *needs* a value, so I gave it a default value here. If you want the default value to be empty, use `O{}` for its argument specifier.

We can add a check to abort with an error message in case the list macro doesn't already exist, which gives the following code:

```
\documentclass{article}

\ExplSyntaxOn

\msg_new:nnn { mypkg } { no-such-list }
  { Can't~ add~ to~ non-existent~ list~ '#1'. }

\NewDocumentCommand { \ini } { O{a} m }
  {
    \tl_if_exist:cTF { list#1 }
      {
        \tl_put_right:cn { list#1 } { {#2} }
      }
      {
        \msg_error:nnn { mypkg } { no-such-list } {#1}
      }
  }

% Iterates over items of a {token}{list}{like}{this} using the specified
% template.
\cs_new_eq:NN \myPrintList \tl_map_inline:Nn

\ExplSyntaxOff

\def\lista{}
\def\listb{}

\ini[a]{tophat}
\ini{default list is a}
\ini[b]{book}
\ini[b]{signpost}

\begin{document}

\lista \par
\myPrintList{\lista}{'#1' }

\medskip
\listb \par
\myPrintList{\listb}{'#1' }

\end{document}
```

![image.png](/image?hash=aeada8ebbff1cef873b7043527705762ab11664ca37fa59ac8128f3d206e9b26)

If you don't want the last separator in the output of `\myPrintList`, consider switching to `seq` variables and using `\seq_use:Nn` or `\seq_use:Nnnn`. But apparently, you're not going to use the lists this way.

Enter question or answer id or url (and optionally further answer ids/urls from the same question) from

Separate each id/url with a space. No need to list your own answers; they will be imported automatically.