# Consecutive Sequences to Process Macro Inside a Macro

I have a macro which uses inner macros to process pairs of arguments. The essential part can be broken down to

\mymacro{\inside{A}{1};\inside{B}{2},\inside{C}{3}}.

Originally I had all pairs processed and then printed, separated by commas, using a sequence to get an output like "1A, 2B, 3C", "1A, 2B" or "1A", for three, two and one arguments, respectively.

Now the requirements have changed and I need the output to be: "1,A 2,B 3.C", "1,A 2.B" or "1.A".

I figured, this could be done with sequences and came up with this solution:

\documentclass{article}
\ExplSyntaxOn

\tl_new:N \l__map_current_tl
\tl_new:N \l__map_tl
\tl_new:N \l__inside_tl

\seq_new:N \l__my_seq
\seq_new:N \l__second_seq

\NewDocumentCommand \mymacro {>{\SplitList{;}} m}
{
\mymacro_process_func:n {#1}
\mymacro_output_func:n
\\
}

\NewDocumentCommand \inside {m m}
{
\inside_process_func:nn {#1} {#2}
}

\cs_new_protected:Npn \inside_process_func:nn #1 #2
{
\tl_if_empty:NTF \l__inside_tl
{ \tl_put_right:Nn \l__inside_tl {#2 !! #1} }
{ \tl_put_right:Nn \l__inside_tl {~ #2 !! #1} }
}

\cs_new_protected:Npn \mymacro_process_func:n #1
{
% make sure token lists and sequences are empty
\tl_clear:N \l__map_current_tl
\tl_clear:N \l__map_tl
\tl_clear:N \l__inside_tl

\seq_clear:N \l__my_seq
\seq_clear:N \l__second_seq

\tl_map_function:nN {#1} \mymacro_map_func:n
\tl_show:N {\l__map_tl}
\seq_set_split:NnV \l__my_seq {;} \l__map_tl
%   \seq_show:N \l__my_seq
\seq_use:Nnnn \l__my_seq {} {} {}
}

\cs_new_protected:Npn \mymacro_map_func:n #1
{
\tl_set:Nn \l__map_current_tl {#1}
\tl_if_empty:NTF \l__map_tl
{ \tl_set_eq:NN \l__map_tl \l__map_current_tl }
{
\tl_put_right:Nn \l__map_tl {;}
\tl_put_right:NV \l__map_tl \l__map_current_tl
}
\tl_set:Nn \l__map_current_tl {#1}
}

\cs_new_protected:Npn \mymacro_output_func:n
{
\seq_set_split:NnV \l__second_seq {!!} \l__inside_tl
%   \seq_show:N \l__second_seq
\seq_use:Nnnn \l__second_seq {.} {,} {.}
}

\ExplSyntaxOff

\begin{document}

Achieved:\\
\mymacro{\inside{A}{1}}
\mymacro{\inside{A}{1};\inside{B}{2}}
\mymacro{\inside{A}{1};\inside{B}{2};\inside{C}{3}}

Desired:\\
1.A \\ 1,A 2.B \\ 1,A 2,B 3.C

\end{document}


As you can see, the code does what it should:

However, I fear it is not very efficient and it looks very dubious to me. For example, I used \l__my_seq in \mymacro_process_func:n with spaces in a previous version:

\seq_set_split:NnV \l__my_seq {;} \l__map_tl
\seq_use:Nnnn \l__my_seq {~} {~} {~}


but the spaces did not appear in the output. (In fact, replacing all ~ by ? prints none, one or two question marks before the output, respectively.)

• Is there a better (shorter) way to without the need to change the use of \mymacro and \inside? (I can't change all the macros in my document)
• Is there, in general, a better approach to this problem?

By the way: I am not sure if my solution (naming, etc.) complies with all rules and conventions, so any comment on this is appreciated as well.

If I understand the requirement it seems you don't need to loop over the input you can simply execute the list, typesetting each item as you go.

\documentclass{article}

\def\mymacro#1{#1\relax}
\def\inside#1#2#3{\ifx\relax#3#2.#1\else#2,#1 \fi}

\begin{document}

Achieved:\\
\mymacro{\inside{A}{1}}\\
\mymacro{\inside{A}{1};\inside{B}{2}}\\
\mymacro{\inside{A}{1};\inside{B}{2};\inside{C}{3}}

Desired:\\
1.A \\ 1,A 2.B \\ 1,A 2,B 3.C

\end{document}

• Wow, this is much shorter. Will it also work if I had to further process the numbers? I did not mention it in the minimal example to keep it minimal but some of the numbers could be ranges which I inserted using a SplitList in the \inside macro as well, using this in an \SIrange.
– Echo
May 17, 2020 at 11:31
• @Echo if the processing of each \inside is independent of others then the same basic technique will work, even if you code the more complicated \inside logic using expl3 May 17, 2020 at 11:55
• Due to my lack of experience I don't see how, but I will take a closer look. I will accept your answer - as it does all I asked for. Thanks for sharing your knowledge.
– Echo
May 17, 2020 at 12:09