1

Cheers to @egreg again for these nice expl3 tricks that finally led me to this \apply macro I use all.the.time:

\documentclass{article}

\usepackage{xparse}

\ExplSyntaxOn

% use: \apply[parse][separator]{function}{list} \NewDocumentCommand{\apply}{ O{##1} O{} m +m}{% \Apply:nnnf { #1 } { #2 } { #3 } { #4 }% }

% The list built and processed from the input items. \seq_new:N \l__Apply_input_seq % The list finally reinjected in the input stream with separators. \seq_new:N \l__Apply_output_seq

% Main function. \cs_new_protected:Nn \Apply:nnnn {% % Build up input list from comma-separated items. \seq_set_from_clist:Nn \l__Apply_input_seq { #4 }% % Define the function to map along the parsed sequence. \cs_set:Npn __Apply_process_multi_args:w% #1 \q_stop % The 'arguments' { \exp_not:n { #3 } } % The 'body' % Wrap the mapped function into a function that only takes 1 argument. \cs_set:Nn __Apply_process_single_arg:n% { __Apply_process_multi_args:w ##1 \q_stop }% % Map the function along the sequence. \seq_set_map:NNn \l__Apply_output_seq \l__Apply_input_seq% {% % Expansion fiddling? __Apply_process_single_arg:f { \exp_not:n { ##1 } }% }% % Reinject into the input stream with the requested separator. \seq_use:Nn \l__Apply_output_seq { #2 }% } % Extend signature so it correctly expands items? \cs_generate_variant:Nn __Apply_process_single_arg:n { f }%

% Extend signature so it correctly expands the input list? \cs_generate_variant:Nn \Apply:nnnn { nnnf }%

\ExplSyntaxOff

\begin{document}

\apply[#1:#2 -> #3][, ]{% #1 and #2 yield #3% }{ first:last -> mid, 5:8 -> 13, good:bad -> well, }

\end{document}

With this I get: example output

To refine my use of \apply, I would love the [parse] argument to provide named slots, that expl3 would convert to expandable csnames within the {function} body. I a nutshell, the above call would be replaced with

\apply[\some:\other -> \result][, ]{%
    \some{} and \other{} yield \result
}{
    first:last -> mid,
    5:8 -> 13,
    good:bad -> well,
}

And why not a mix of both worlds?

\apply[#1:\other -> #2][, ]{%
    #1 and \other{} yield #2%
}{
    first:last -> mid,
    5:8 -> 13,
    good:bad -> well,
}

Is this achievable with expl3? What could I get started with?

iago-lito
  • 1,472

0 Answers0