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
expl3package andLATEX3programming - 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:
nUnexpanded token or braced token list.This is a standard TEX undelimited macro argument.
NSingle 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.
pPrimitive 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,FThese 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:nnTFnor\peek_after:Nware expandable, so\cs_new_protected:Nnshould be used. - Use expl3 inside a LaTeX2e macro
Instead of
\newcommand, it's better to use\cs_new_protected:Npn, if not\NewDocumentCommandofxparse(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:Npnor\cs_new_protected:Npn.Beware that you should use
\cs_new_protected:Npnor\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:nis 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:Npnor similar, and not\cs_new:Npn, etc. - latex3 complaining about Undefined control sequence. But it is defined!
Use
\cs_new_protected:Npnwhen 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\defor\gdefin 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:nfunction 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:owould be\exp_args:No \__a_one:n...
There would be no other practical way for a hypothetical
\cs_new_protected:Nn \__a_one:ohandling the required expansion to basically define\__a_one:nunder 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:Nnis doing? - What
\cs_new_protectedis? 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:Npnis exactly\protected\gdefwith a test to see if the function (theNin 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. – Phelype Oleinik Nov 11 '19 at 02:56\protected\long\gdef. See siracusa' answer. – Phelype Oleinik Nov 11 '19 at 03:20