9

If you need arguments preprocessed/expanded before TeX passes them to a macro, you can do two things in expl3:

  1. Use \cs_generate_variant:Nn for generating a variant of the macro where the arguments get preprocessed.
  2. Use \exp_args:N...

In the first example below,
\mymodule_foo:o { \mymodule_bar: }
generates the same message as
\exp_args:No \mymodule_foo:n { \mymodule_bar: }.

The questions are:

Besides

  • the goal of reducing the size of one's .tex-input-files,
  • the memory consumption during the LaTeX-run, which—provided it does not appear in the definition texts of many macros—should be lower for the \exp_args:N... variant, because no additional macro needs to be stored,
  • readability of code
  • the duration/runtime of the LaTeX run

, are there other criteria/conditions for preferring one of the two approaches?

If yes: Which ones?

Which of the two approaches is faster?

\ExplSyntaxOn

\msg_new:nnnn {mymodule} {generic} {#1} {}
\cs_new:Nn \mymodule_foo:n 
 {
   \msg_term:nnn {mymodule} {generic} {
     This~is~the~argument~of~\mymodule_foo: #1
   }
 }
\cs_generate_variant:Nn \mymodule_foo:n { o }
\cs_new:Nn \mymodule_bar:
 {
   Toplevel~expansion~of~\mymodule_bar:
 }


\mymodule_foo:o {\mymodule_bar:}

\exp_args:No \mymodule_foo:n {\mymodule_bar:}

\stop

I mentioned readability because with \exp_args:N... the code quickly becomes confusing for the inexperienced when dealing with multiple arguments that need to be pre-processed:

\ExplSyntaxOn

\msg_new:nnnn {mymodule} {generic} {#1} {}
\cs_new:Nn \mymodule_foo:nnn 
 {
   \msg_term:nnn {mymodule} {generic} { 1st~argument~of~\mymodule_foo: #1 }
   \msg_term:nnn {mymodule} {generic} { 2nd~argument~of~\mymodule_foo: #2 }
   \msg_term:nnn {mymodule} {generic} { 3rd~argument~of~\mymodule_foo: #3 }
 }
\cs_generate_variant:Nn \mymodule_foo:nnn { ooo }
\cs_new:Nn \mymodule_bar: { Toplevel~expansion~of~\mymodule_bar: }
\cs_new:Nn \mymodule_bas: { Toplevel~expansion~of~\mymodule_bas: }
\cs_new:Nn \mymodule_bat: { Toplevel~expansion~of~\mymodule_bat: }

% This is readable:

\mymodule_foo:ooo {\mymodule_bar:}{\mymodule_bas:}{\mymodule_bat:}

\msg_term:nnn 
    {mymodule} {generic} 
    { ------------------------------------------------------------------- }

% This is sort of readable:

\exp_args:Nooo \mymodule_foo:nnn {\mymodule_bar:}{\mymodule_bas:}{\mymodule_bat:}

\msg_term:nnn 
    {mymodule} {generic} 
    { ------------------------------------------------------------------- }

% This might occur confusing:

\exp_args:Nno \use:n {
  \exp_args:Nno \use:n {
    \exp_args:No \mymodule_foo:nnn {\mymodule_bar:}
  } {\mymodule_bas:}
} {\mymodule_bat:}

\stop
1
  • Side note, I have a kind-of personal package to automatically generate \cs_generate_variant:Nn lines appropriately for a file (although writing such a thing wouldn't be particularly difficult anyway)
    – user202729
    Apr 7 at 17:44

1 Answer 1

8

In general, the recommendations from the team are focussed on readability: the performance differences here are tiny. The approach we promote is to strongly favour \cs_generate_variant:Nn, with 'direct' use of \exp_args:N... reserved for

  • Places where a variant is only used once
  • Cases where using a variant is impossible: typically where a csname is dynamically generated

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.