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, 2022 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

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .