2

This question is kind-of follow-up to answer given to this question: How to iterate over a comma separated list?

The difference is, that I want to iterate over a csv list stored in a macro \myTerms. In following MWE the list in \myTerms seems to be taken literally and not parsed as a CSV. I tryed to fix it with \expanded{}, but it doesnt seem to work.

MWE:

\documentclass{article}

\ExplSyntaxOn

\NewDocumentCommand{\myList}{mm}
 {
  \clist_set:Nn \l_tmpa_clist { #1 }
  \clist_use:Nnnn \l_tmpa_clist { #2 } { #2 } { #2 }
 }
 \ExplSyntaxOff

\newcommand{\mySeparator}{\textbullet}

\newcommand{\makeMyList}[1]{
  \begingroup
    \scshape\myList{#1}{\mySeparator}
  \endgroup
}

\newcommand{\myTerms}{test, another test}

\begin{document}
\makeMyList{\expanded{\myTerms}}
\end{document}

Desired output is achieved when I am not using macro myTerms and simply write out the list to \makeMyList argument, like so:

Desired output:

\documentclass{article}

\ExplSyntaxOn

\NewDocumentCommand{\myList}{mm}
 {
  \clist_set:Nn \l_tmpa_clist { #1 }
  \clist_use:Nnnn \l_tmpa_clist { #2 } { #2 } { #2 }
 }
 \ExplSyntaxOff

\newcommand{\mySeparator}{\textbullet}

\newcommand{\makeMyList}[1]{
  \begingroup
    \scshape\myList{#1}{\mySeparator}
  \endgroup
}

\begin{document}
\makeMyList{test, another test}
\end{document}

That led me to think that expansion control with \expanded{} is needed, but I seem to be making a different mistake. How can I fix that?

3

When you use expl3 I'd advocate to stick to the means of expansion provided by that as long as you don't do low-level programming. What I mean with that is: you shouldn't have to bother to expand the list as input, I think it's better to let that be handled at the expl3 level.

Your usage of \expanded doesn't work, because before \expanded can do its job your \makeMyList will grab its arguments and treat \expanded{\myTerms} as the input, doesn't find a comma and so uses that as a single term.

The expansion at the expl3 level could be done in two different ways:

  • educated guess, if only a single argument is provided it is very likely that this is a macro storing the values
  • provide a "switch" at \makeMyList, e.g., via a star, in which case we could use \exp_args:No or similar.

The following implements both, but uses \expandafter for the second approach instead of the expl3-layer:

\documentclass{article}

\ExplSyntaxOn
\NewDocumentCommand{\myList}{mm}
  {
    \tl_if_single:nTF {#1}
      {
        % if the single item is a group we don't expand it
        \tl_trim_spaces_apply:nN {#1} \tl_if_head_is_group:nTF
          { \clist_set:Nn }
          {
            % if it's no group it must be N-type, and the test for group is
            % faster
            % there might be spaces around #1 but those will be removed by TeX's
            % argument grabbing, so don't hurt
            \token_if_expandable:NTF #1
              \clist_set:NV
              \clist_set:Nn
          }
      }
      { \clist_set:Nn }
        \l_tmpa_clist {#1}
    \clist_use:Nn \l_tmpa_clist {#2}
  }
\ExplSyntaxOff

\newcommand{\mySeparator}{\textbullet}

\NewDocumentCommand \makeMyList { s m }
  {
    \begingroup
      \scshape
      \IfBooleanTF {#1}
        {\expandafter\myList\expandafter{#2}\mySeparator}
        {\myList{#2}\mySeparator}%
    \endgroup
  }

\newcommand{\myTerms}{test, another test}

\begin{document}
% expansion-guess at the expl3 level
\makeMyList{\myTerms}\par
\makeMyList{\myTerms,abc}

% expansion of first token in the list by the interface
\makeMyList*{\myTerms}\par
\makeMyList*{\myTerms,abc}
\end{document}

EDIT: added more tests as suggested by @AndrewStacey.

enter image description here

2
  • You could further test to see if that one character in the single token list was active. Sep 11 '21 at 9:32
  • 1
    @AndrewStacey better tests added.
    – Skillmon
    Sep 11 '21 at 9:39
2

The problem with your proposal is that the \expanded doesn't get seen until too late. Depending on exactly what it is you want to achieve, there are a few ways to do this. A simple one is to change the \clist_set:Nn to \clist_set:NV. This takes the value of the macro as the list to use. You'd also need to remove the braces around the #1. This does a single expansion so if your list contains macros then they don't get expanded.

(I'm not on a device where I can easily test this right now so it is possible that you'd need some other tweaks.)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.