3

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.

  • 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 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? – Denis Bitouzé Jan 4 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 at 15:20
  • @ChristianHupfer Okay for a single cell but, here, the whole line is concerned. – Denis Bitouzé Jan 4 at 15:26
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

  • 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? – Denis Bitouzé Jan 4 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 at 15:52

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.