After my question Undefined control sequence while adding a new parameter to a existing \ExplSyntaxOn code, I trying to fully understand the code behind it. So far, so good, with:
- The
expl3
package andLATEX3
programming - https://www.texdev.net/2010/05/23/from-newcommand-to-newdocumentcommand/
- Using key values in \NewDocumentCommand
- Always use \NewDocumentCommand instead of \newcommand?
I found a lot of explanations, except one. What are the arguments to this \cs_new_protected:Npn
command? A confusing thing is:
...
\cs_new_protected:Npn \user_name_refs:nnnn #1#2#3#4
{
...
I understand that \user_name_refs:nnnn #1#2#3#4
refers to my function named \user_name_refs
which receives 4 parameters which are nnnn
, Unexpanded token or braced token list
. But what the Npn
are doing in the \cs_new_protected:Npn
?
These Npm
argument seems to be the same as these from The expl3
package and LATEX3
programming
All functions have a base form with arguments using one of the following argument specifiers:
n
Unexpanded token or braced token list.This is a standard TEX undelimited macro argument.
N
Single token (unlike n, the argument must not be surrounded by braces).A typical example of a command taking an N argument is
\cs_set
, in which the command being defined must be unbraced.
p
Primitive TEX parameter specification.This can be something simple like
#1#2#3
, but may use arbitrary delimited argument syntax such as:#1,#2\q_stop#3
. This is used when defining functions.
T,F
These are special cases of n arguments, used for the true and false code in conditional commands....
Further argument specifiers are available as part of the expansion control system. These are discussed in the next section,
Expansion control
.
Actually, this The expl3
package and LATEX3
programming, seems quite complete. Is there another one out there? There is no mention of \cs_new_protected
on The expl3
package and LATEX3
programming guide. May be it should be added to it?
On these questions, I can find small tips about what \cs_new_protected
does:
- Convert token to string in LaTeX3
You have to do a loop over the characters to check. Be careful that neither
\str_if_in:nnTF
nor\peek_after:Nw
are expandable, so\cs_new_protected:Nn
should be used. - Use expl3 inside a LaTeX2e macro
Instead of
\newcommand
, it's better to use\cs_new_protected:Npn
, if not\NewDocumentCommand
ofxparse
(probably even a better choice). - A LaTeX3 new macro/function definition problems
If the command you want to define has no signature, you must define it with
\cs_new:Npn
or\cs_new_protected:Npn
.Beware that you should use
\cs_new_protected:Npn
or\cs_new_protected:Nn
(same rules apply) whenever the code contains non expandable functions (those without a red full or hollow star in the manual). Not the case here, because\int_eval:n
is fully expandable. - A guide to understanding expandability: when to write protected functions and when not to
So the 'correct' way to write LaTeX3 code is that if you use anything that is not expandable (i.e. not starred in the documentation) in your code, then you have to use
\cs_new_protected:Npn
or similar, and not\cs_new:Npn
, etc. - latex3 complaining about Undefined control sequence. But it is defined!
Use
\cs_new_protected:Npn
when the function does unexpandable jobs (such as setting token lists or sequences).
But no explicit explanation about what are these Npm
arguments to the \cs_new_protected
... Although, LaTeX3: Correct way to define a macro with :o, gives a little more light after quoting the file The LATEX3 interfaces
from l3kernel – LATEX3 programming conventions
There's no magic involved. When you say
\cs_new_protected:Nn
, you're using\def
or\gdef
in disguise. ... it's undoubtedly better to go step by step:\cs_new_protected:Nn \__a_one:n { ... } \cs_generate_variant:Nn \__a_one:n { o }
Because the
\__a_one:n
function would have to be defined anyway. So there's no point in setting up a complicated mechanism for this.To be more specific, after that code, the meaning of
\__a_one:o
would be\exp_args:No \__a_one:n
...
There would be no other practical way for a hypothetical
\cs_new_protected:Nn \__a_one:o
handling the required expansion to basically define\__a_one:n
under the hood and then applying\cs_generate_variant:Nn
.
So, I have to use this \cs_new_protected
with \cs_generate_variant:Nn
. But what this \exp_args:No \__a_one:n
means? Then, the same question applies to:
- What
\cs_generate_variant:Nn
is doing? - What
\cs_new_protected
is? A function? A modifier? A reserved keyword? A function declaration syntax?
Related questions
- Should something like \cs_generate_variant:Nn \foo_my_func:n { N } throw an error?
- What is a function's signature? [LaTeX3]
- expl3 function for fixed number of expansion steps
- Is it possible to separate the declaration of a LaTeX3 variable of type control-sequence from the act of setting its value?
- What's the purpose of \use_none_delimit_by_q_nil:w and friends in LaTeX3?
- LaTeX3 iteration and token list comparisons-code improvement
- Define an expandable function for comparing a token list to a string in LaTeX3
- f-type expansion
- Writing a token list conditional with expl3
- Protected expansion in expl3
- Passing more arguments to mapping functions in LaTeX3
- Effiency and speed of expl3 "datatypes"
- How to test whether a token variable exists?
- Complete example from LaTeX3 intro
- Why are there so many underscores in LaTeX3 commands?
- How to use \cs_generate_variant:Nn to compare token lists?
- Comparing LaTeX3 token list to string
\cs_new_protected:Npn
is exactly\protected\gdef
with a test to see if the function (theN
in the argument spec) is already defined (and an error in that case). Take a look at section 3 control sequences and functions (page 10) of The LaTeX3 Interfaces.\protected\long\gdef
. See siracusa' answer.