2

The following code compiles, but does not do what I want:

\documentclass{article}

\usepackage{xparse}

\newcommand{\attribute}[1]{\mathbf{#1}}
\newcommand{\constant}[1]{\mathsf{#1}}

\ExplSyntaxOn
\NewDocumentCommand \extrelationrow { m m } {
  \seq_set_split:Nnn \shepi_vals {,} {#2}
  \seq_pop_right:NN \shepi_vals \shepi_last
  \seq_map_inline:Nn \shepi_vals {#1{##1}} % <=====
  %\seq_map_inline:Nn \shepi_vals {#1{##1} & }
  #1{\shepi_last}
  \\
}
\ExplSyntaxOff

\begin{document}

\[\begin{array}{llll}
  \extrelationrow{\attribute}{A,B,C,D}
  \extrelationrow{\constant}{e,f,g,h}
\end{array}\]

\end{document}

If you comment the marked line with the commented one, then compilation fails with the following surprising (at least for me) error:

! Undefined control sequence.
<argument> \shepi_last 

l.21   \extrelationrow{\attribute}{A,B,C,D}

If I accumulate the #1{##1} values in some auxiliary list and use seq_use:Nn, it works but I have to declare this auxiliary list outside of the function and use seq_clear:N. I believe that accumulating takes more resources and is unnecessary here. Anyway I would like to understand why my variable \shepi_last disappears when I add an & on the above line.

3

\seq_map_inline:Nn cannot straddle alignment cells.

You can process the sequence to adorn each item with \seq_set_map:NNn and then use \seq_use:Nn.

\documentclass{article}

\usepackage{xparse}

\newcommand{\attribute}[1]{\mathbf{#1}}
\newcommand{\constant}[1]{\mathsf{#1}}

\ExplSyntaxOn
\seq_new:N \l_shepi_vals_in_seq
\seq_new:N \l_shepi_vals_out_seq
\NewDocumentCommand \extrelationrow { m m }
 {
  \seq_set_split:Nnn \l_shepi_vals_in_seq {,} {#2}
  \seq_set_map:NNn \l_shepi_vals_out_seq \l_shepi_vals_in_seq { \exp_not:n { #1{##1} } }
  \seq_use:Nn \l_shepi_vals_out_seq { & }
  \\
}
\ExplSyntaxOff

\begin{document}

\[
\begin{array}{llll}
  \extrelationrow{\attribute}{A,B,C,D}
  \extrelationrow{\constant}{e,f,g,h}
\end{array}
\]

\end{document}

Please, note the proper naming of variables, which should have a prefix and a suffix, in this case l_ (local) and _seq (sequence).

enter image description here

Differently from \seq_map_inline:Nn, \seq_use:Nn delivers its result in one swoop, so it can be used in an alignment cell. It adds the tokens in the second argument only between items, so no pop is necessary.

For technical reason, the third argument to \seq_set_map:NNn is fully expanded, so \exp_not:n has to be used.

  • I knew that I would get valuable advice in addition to a solution to my problem. My bad for not checking the l3candidates interface. Thank you very much for your help! Latex3 is actually changing my life, I love it! :-) – Fabian Pijcke Feb 23 '17 at 6:32
  • As a side question, is there any reason you "declare" the two sequences outside of the command? The code works without these two lines but maybe there is a performance argument ongoing here? – Fabian Pijcke Feb 23 '17 at 7:00
  • 1
    @FabianPijcke It's good programming style to declare the variables we're going to use. For implementation reasons using undeclared token list or sequence variables works, but it's a fact one shouldn't rely upon. – egreg Feb 23 '17 at 9:02

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.