6

The following code allows me to produce series easily (see examples below the code):

\documentclass{article}

\ExplSyntaxOn
\NewDocumentCommand \simpleseq { m m m } {
  \seq_set_split:Nnn \l_inner_seq {,} {#3}
  \seq_set_map:NNn \l_part_seq \l_inner_seq {\exp_not:n {#2}}
  \seq_use:Nn \l_part_seq {#1 \allowbreak}
}

\NewDocumentCommand \seq { O{,} O{\dots} D||{##1} s m s } {
  \seq_set_split:Nnn \l_outer_seq {;} {#5}
  \seq_set_map:NNn \l_final_seq \l_outer_seq {\exp_not:n {\simpleseq{#1}{#3}{##1}}}
  \IfBooleanT #4 { #2 #1 \allowbreak }
  \seq_use:Nn \l_final_seq {#1 \allowbreak #2 #1 \allowbreak }
  \IfBooleanT #6 { #1 \allowbreak #2 }
}
\ExplSyntaxOff

\begin{document}

\[\seq[-] {1,2,3}\] % 1 - 2 - 3
\[\seq{1,2;5,6;10,11}\] % 1, 2, ..., 5, 6, ..., 10, 11
\[\seq*{1,2;5,6}\] % ..., 1, 2, ..., 5, 6
\[\seq[\ ][---]{1,2;5,6}*\] % 1 2 --- 5 6 ---

\[\seq |A_{##1}| {1,2;7,8}*\] % A_1, A_2, ..., A_5, A_6
% How to alter commands so that I can use either of these versions?
%\[\seq |A_{#1}| {1,2;7,8}*\]
%\[\seq |A_{\v}| {1,2;7,8}*\]

\end{document}

I'm concerned with the last example. I'm not happy with having to use ##1 as argument. I want either #1 or \v.

Besides any advice about the quality of this code is welcome, I'm an Expl3 beginner ...

7

Define a temporary function:

\documentclass{article}
\usepackage{amsmath}
\usepackage{xparse}

\ExplSyntaxOn

\seq_new:N \l_fabian_inner_in_seq
\seq_new:N \l_fabian_inner_out_seq
\seq_new:N \l_fabian_outer_in_seq
\seq_new:N \l_fabian_outer_out_seq

\NewDocumentCommand \seq { O{,} O{\dots} d|| s m s }
 {
  \IfNoValueTF{#3}
   { \cs_set_eq:NN \__fabian_inner_process:n \use:n }
   { \cs_set_protected:Nn \__fabian_inner_process:n { #3 } }
  \IfBooleanT #4 { #2 #1 \allowbreak }
  \fabian_outer:nnn { #1 } { #2 } { #5 }
  \IfBooleanT #6 { #1 \allowbreak #2 }
 }
\cs_new_protected:Nn \fabian_outer:nnn
 {
  \seq_set_split:Nnn \l_fabian_outer_in_seq {;} {#3}
  \seq_set_map:NNn \l_fabian_outer_out_seq \l_fabian_outer_in_seq
   {
    \exp_not:n { \fabian_inner:nn { #1 } { ##1 } }
   }
  \seq_use:Nn \l_fabian_outer_out_seq {#1 \allowbreak #2 #1 \allowbreak }
 }
\cs_new_protected:Nn \fabian_inner:nn
 {
  \seq_set_split:Nnn \l_fabian_inner_in_seq { , } { #2 }
  \seq_set_map:NNn \l_fabian_inner_out_seq \l_fabian_inner_in_seq
   { \exp_not:n {\__fabian_inner_process:n { ##1 } } }
  \seq_use:Nn \l_fabian_inner_out_seq { #1 }
 }
\ExplSyntaxOff

\begin{document}
\begin{gather}
\seq[-] {1,2,3} % 1 - 2 - 3
\\
\seq{1,2;5,6;10,11} % 1, 2, ..., 5, 6, ..., 10, 11
\\
\seq*{1,2;5,6} % ..., 1, 2, ..., 5, 6
\\
\seq[\ ][\text{---}]{1,2;5,6}* % 1 2 --- 5 6 ---
\\
\seq |A_{#1}| {1,2;7,8}*
\\
\seq |A_{#1}| *{1,2;7,8}*
\end{gather}
\end{document}

enter image description here

2
  • Nice solution, cleaner in many aspects, yet I'm not sure to understand why you introduced the \fabian_outer command. I learned a lot of things through your solution tho, thank you! – Fabian Pijcke Feb 23 '17 at 11:03
  • 2
    @FabianPijcke It's better to reserve the code in \NewDocumentCommand to simple tasks, deferring more complex ones to inner functions; typically, the main job of \NewDocumentCommand is to parse the arguments and do the appropriate calls to inner functions. – egreg Feb 23 '17 at 12:56
1

The following modification works, but seems really really really unsafe and I won't use it unless someone tells me it's a good idea (and gives me arguments so that I believe him :p)

\NewDocumentCommand \simpleseq { m m m } {
  \seq_set_split:Nnn \l_inner_seq {,} {#3}
  \seq_set_map:NNn \l_part_seq \l_inner_seq {\exp_not:n {\def\v{##1}#2}}
  \seq_use:Nn \l_part_seq {#1 \allowbreak}
}

After some tests it seems not so unsafe ...

I just learned that \def binds locally (and not globally as I believed).

I made some tests where I \def'ed a macro \v, use it, use my commands, then use \v again, and all works as expected.

Anyway I'm still open to a more Latex3-ish solution :-)

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.