TransWikia.com

Parse input into commands in expl3

TeX - LaTeX Asked by iago-lito 'considering leaving on March 14, 2021

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?

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP