5

It is rather common to have to apply special treatment for first and last items of a sequence. I wonder what the best ways to treat these cases in expl3's \seq_map_inline.

For instance, suppose I'd like to create the following tabular (ASCII art):

Words foo
      ---
      bar
      ---
      baz

where the words "foo", "bar", "baz" are the items of a sequence. This could be done the following way:

\documentclass{article}
\usepackage{expl3}
\begin{document}
\ExplSyntaxOn

\seq_new:N \l_my_sequence_seq

\seq_set_from_clist:Nn \l_my_sequence_seq {foo,bar,baz}

\begin{tabular}{ll}
  \seq_map_inline:Nn \l_my_sequence_seq {
    \int_gincr:N \g_tmpa_int
    \int_compare:nNnT {\g_tmpa_int}={1}{Words}
    & #1
    \int_compare:nNnF {\g_tmpa_int}={\seq_count:N \l_my_sequence_seq}{\\\cline{2-2}}
  }
\end{tabular}
\ExplSyntaxOff
\end{document}

But I wonder if there are better ways to achieve the same result.

4
  • Shouldn't the last item have not a following cline? I think, \seq_map_inline is the wrong way in a tabular environment
    – user31729
    Jan 4, 2019 at 15:14
  • @ChristianHupfer If I'm right, that's the case: there isn't any \cline after "baz". Why wouldn't you recommend \seq_map_inline in a tabular environment and what would recommend instead? Jan 4, 2019 at 15:19
  • \seq_map_inline:Nn is not really made for starting in one table cell (or say group) and stopping in another one.
    – user31729
    Jan 4, 2019 at 15:20
  • @ChristianHupfer Okay for a single cell but, here, the whole line is concerned. Jan 4, 2019 at 15:26

2 Answers 2

4

I suggest to remove the test for the 1st item and popping the items from a temporary list in a \seq_map_function:NN approach rather.

The popping occurs inside a group, so \l_tmpa_seq is not really hurt in the mapping loop.

Note that \bitouze_map_function:n requires one argument (which is actually the current \seq_item, but this argument is not used at all here!)

\documentclass{article}
\usepackage{expl3}
\begin{document}
\ExplSyntaxOn

\seq_new:N \l_my_sequence_seq

\seq_set_from_clist:Nn \l_my_sequence_seq {foo,bar,baz}

\begin{tabular}{ll}
  \seq_map_inline:Nn \l_my_sequence_seq {
    \int_gincr:N \g_tmpa_int
    \int_compare:nNnT {\g_tmpa_int}={1}{Words}
    & #1
    \int_compare:nNnF {\g_tmpa_int}={\seq_count:N \l_my_sequence_seq}{\\\cline{2-2}}
  }
\end{tabular}


\seq_set_eq:NN \l_tmpa_seq \l_my_sequence_seq

\cs_new:Nn \bitouze_map_function:n {
  &\seq_gpop_left:NN \l_tmpa_seq \l_tmpa_tl 
  \tl_use:N \l_tmpa_tl \tabularnewline
  \seq_if_empty:NTF \l_tmpa_seq{% False branch
    \cline{2-2}
  }
}


\begin{tabular}{ll}
  Words 
  \seq_map_function:NN \l_tmpa_seq \bitouze_map_function:n
\end{tabular}


\ExplSyntaxOff
\end{document}

enter image description here

4

I guess you want to detach the last element of the sequence:

\documentclass{article}
\usepackage{xparse}

\ExplSyntaxOn
\seq_new:N \l_db_wordlist_seq
\tl_new:N \l_db_wordlist_last_tl

\NewDocumentCommand{\wordlist}{m}
 {
  \seq_set_from_clist:Nn \l_db_wordlist_seq { #1 }
  \seq_pop_right:NN \l_db_wordlist_seq \l_db_wordlist_last_tl
  \begin{tabular}{ll}
  Words \seq_map_function:NN \l_db_wordlist_seq \__db_wordlist_do:n
  & \l_db_wordlist_last_tl
  \end{tabular}
 }
\cs_new_protected:Nn \__db_wordlist_do:n { & #1 \\ \cline{2-2} }
\ExplSyntaxOff

\begin{document}

\wordlist{foo,bar,baz}

\end{document}

enter image description here

2
  • If I understand well, your advise for the special treatment for the first and last items of a sequence is to (1) pop and store them in ..._first_tl and ..._last_tl token lists, (2) treat them through these token list and treat the rest of the sequence with a (mapped) function? Jan 4, 2019 at 15:48
  • @DenisBitouzé This depends on what you actually need to do; for this application you can wrap in a function the treatment of all elements except the last.
    – egreg
    Jan 4, 2019 at 15:52

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .