add tag
निरंजन
Consider the following example:

```#
\documentclass[border=1cm]{standalone}
\usepackage{array,booktabs}

\begin{document}
\ExplSyntaxOn
\begin { tabular } { l l }
  \toprule
  \clist_map_inline:nn {
    \TeX,
    \LaTeX,
    PDF \LaTeX
  } {
    #1 & \texttt { \tl_to_str:n { #1 } } \\
    \midrule
  } \\ % Why is this required?
  \bottomrule
  \multicolumn { 2 } { r } { \emph { End~ of~ table. } } \\
\end { tabular }
\ExplSyntaxOff
\end{document}
```

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

As described in the comments, I am not able to understand why the `\\` on line 15 is required. The following is the expected result once `\clist_map_inline:nn` is executed:

```
\documentclass[border=1cm]{standalone}
\usepackage{array,booktabs}

\begin{document}
\ExplSyntaxOn
\begin { tabular } { l l }
  \toprule
  \TeX       & \texttt { \tl_to_str:n { \TeX } } \\
  \midrule
  \LaTeX     & \texttt { \tl_to_str:n { \LaTeX } } \\
  \midrule
  PDF \LaTeX & \texttt { \tl_to_str:n { PDF \LaTeX } } \\
  \midrule
  \bottomrule
  \multicolumn { 2 } { r } { \emph { End~ of~ table. } } \\
\end { tabular }
\ExplSyntaxOff
\end{document}
```

Note that this code _does not_ have the `\\` that we see on line 15 in the first code. Agreed that this adds a `\midrule` over the `\bottomrule` which is not desired, but that's a separate issue and can be dealt with later. As of now, I am curious about the extra `\\` that the code requires.
Top Answer
Skillmon
The reason it's necessary is that `\noalign` (the primitive used by `\bottomrule`) must be the first unexpandable token inside an alignment row. As such, the minimal example that breaks for the same reason as yours is the following:

```
\begin{tabular}{c}
\relax\bottomrule
\end{tabular}
```

-----

# Why does `\clist_map_inline:nn` have this issue?

You need to understand how `\clist_map_inline:nn` is implemented to understand what the unexpandable contents left by it are. In short it looks something like this:

```
<setup-code defining an internal auxiliary function>
<loop>
<setup-code restoring the earlier definition of the auxiliary function>
```

(in reality that might be differently implemented with a level counter and something along the lines, but that's the gist of it, the setup has to be reverted, regardless of how that setup is done)

So, since the `inline`-mappers need to maintain and restore a state (such that you can nest loops inside each other) they need to execute some unexpandable code at the start and end of the loop. That unexpandable code breaks your `\bottomrule`, since now it's no longer the first thing in its row.

-------

# What to do?

If your table allows it the easiest fix is to put the `\\` at the start of your inline function, then you're free to put your `\\` after the end of the `inline`-mapper and have no problem with `\bottomrule`. That's not the case here.

Another possibility is to build the table body inside a variable and then expand that variable.

```
\documentclass[border=1cm]{standalone}
\usepackage{array,booktabs}

\begin{document}
\ExplSyntaxOn
\begin { tabular } { l l }
  \toprule
  \tl_clear:N \l_tmpa_tl
  \clist_map_inline:nn {
    \TeX,
    \LaTeX,
    PDF \LaTeX
  } {
    \tl_put_right:Nn \l_tmpa_tl
      {
        #1 & \texttt { \tl_to_str:n { #1 } } \\
        \midrule
      }
  }% \\ % Why is this required?
  \l_tmpa_tl
  \bottomrule
  \multicolumn { 2 } { r } { \emph { End~ of~ table. } } \\
\end { tabular }
\ExplSyntaxOff
\end{document}
```

We have to switch the `\midrule` around since otherwise you'll end up with `\midrule\bottomrule` which doesn't look nice (from now on I drop the preamble and only put the `tabular` environment into the listings):

```
\begin { tabular } { l l }
  \toprule
  \tl_clear:N \l_tmpa_tl
  \clist_map_inline:nn {
    \TeX,
    \LaTeX,
    PDF \LaTeX
  } {
    \tl_put_right:Nn \l_tmpa_tl
      {
        \midrule
        #1 & \texttt { \tl_to_str:n { #1 } } \\
      }
  }% \\ % Why is this required?
  \tl_tail:N \l_tmpa_tl
  \bottomrule
  \multicolumn { 2 } { r } { \emph { End~ of~ table. } } \\
\end { tabular }
```

In modern LaTeX with modern PCs, building the table body isn't that bad, performance and memory capacity is good enough, but for *big* table's you'll hit a wall sooner or later (if you don't use LuaTeX which can dynamically allocate more memory, but then the code will be slow nevertheless). You can get better performance using `\tl_build_...` functions, but you'll get even better performance and less memory usage if you turn to a fully expandable loop:

```
\cs_new:Npn \my_tbl_builder:n #1
  {
    % \exp_stop_f: doesn't hurt in front of a `\noalign`
    \exp_stop_f: \midrule
    #1 & \texttt { \tl_to_str:n {#1} } \\
  }
\begin { tabular } { l l }
  \toprule
  % we could use `\exp_not:n` in the definition of `\my_tbl_builder:n` and use
  % `\tl_tail:e` here, but that would use slightly more memory, and this was
  % about saving memory
  \exp_after:wN \use_none:n \exp:w \exp_end_continue_f:w
  \clist_map_function:nN {
    \TeX,
    \LaTeX,
    PDF \LaTeX
  }
  \my_tbl_builder:n
  \bottomrule
  \multicolumn { 2 } { r } { \emph { End~ of~ table. } } \\
\end { tabular }
```

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.