# Special treatment for first and last items in \seq_map_inline

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

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}


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}


• 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