2

I am reading the documentation about Argument Specifiers in 1.1 Naming functions and variables of interfaces.pdf, where each argument is represented by a single letter.

I am confused of the argument specifier N and n. The document states that N and n mean no manipulation of a single token for N and no manipulation of a set of tokens given in braces for n.

I need some examples, because I see many functions having N then n. Does that mean the the function takes two arguments ?

Veak
  • 1
  • I cannot answer, but am interested in whatever answers are provided by others. As you noted, the documentation explanation is a bit mystifying. – rallg Oct 01 '23 at 19:02
  • 1
    yes, each letter denotes an argument, so \foo:Nn would be used as \foo:Nn \something {some tokens} – David Carlisle Oct 01 '23 at 19:13
  • 2
    that is how you can tell the number of arguments from this signature, as explained in your earlier question – David Carlisle Oct 01 '23 at 19:17
  • "where each argument is represented by a single letter" <- Explanation and answer for your question, stated in your question. – Skillmon Oct 01 '23 at 19:24
  • I am starting to make sense of things. For instance, take \cs_new:Nn \function_name:n Whilst the N means an argument, it is an argument to \cs_new, rather than an argument to \function_name. – Veak Oct 01 '23 at 19:49
  • The name is \cs_new:Nn not \cs_new (etc.) – Joseph Wright Oct 01 '23 at 19:50
  • Isn't the command \cs_new with Argument Specifier :Nn appended ? – Veak Oct 01 '23 at 19:56
  • @Fluffy no, \cs_new:Nn is a single token, as is \feuds_newteorema_simple:nn – David Carlisle Oct 01 '23 at 20:10
  • 1
    I thought that name of the new function was \feuds_newteorema_simple with the Argument Specifier being :nn to signify two arguments are to be passed to \feuds_newteorema_simple. Rather, you state that the names are \cs_new:Nn and \function_name:n meaning that : is an acceptable character like _ in function names. Latex in turn reads the function name from which Latex extracts the Argument Specifier. Correct ? – Veak Oct 01 '23 at 20:15
  • the specifier is almost never used at run time, it's just a naming convention, the only exception is (as explained in your earlier question) some definition forms read the specifcation part to work out how many arguments there are. – David Carlisle Oct 01 '23 at 20:21
  • the specification is mostly for humans, \cs_new:Nn tells you the usage is \cs_new:Nn\foo{xxx} with one cstoken and one brace group, whereas the variant \cs_new:cn has usage \cs_new:cn{foo}{xxx} where c means it takes a token list of characters and makes the csname before passing to the underlying command. – David Carlisle Oct 01 '23 at 20:27
  • You named the functions that way so programmers would not have to look the function definition, but deduce it from the function name. In practice you could have used two different names for \cs_new:Nn and \cs_new:Npn. Nevertheless, it was decided to just include a p to tell you it uses parameter text, rather than invent a completely different name. – Veak Oct 01 '23 at 20:45
  • Have I got it right, now ? – Veak Oct 01 '23 at 21:52
  • Functions in L3 are built of three parts: \<module>_<description>:<args>, all three parts together built a single function name, e.g., \tl_trim_spaces:n. The <module> part is just name-spacing, as TeX has no built in concept of name spaces (in our example tl is the module), the <description> should briefly tell what the function should do (trim_spaces), and then the <args> tell us which arguments the function takes and of what kind (our example takes a single n-type argument, so any number of tokens surrounded by braces). – Skillmon Oct 01 '23 at 22:14
  • So, your \cs_new:Nn and \cs_new:Npn examples are of module cs, they create a new one (new), and the first one takes a single token, and then a normal argument of any number of tokens in braces. The second one however takes a single token, then parameter text, and then any number of tokens in braces. Their behaviour is fundamentally the same (create a new something) as the description tells us, but they take different arguments to reach that goal (here a different number of arguments). – Skillmon Oct 01 '23 at 22:17
  • That was very enlightening. – Veak Oct 01 '23 at 23:05

1 Answers1

3

User level commands are comparatively much fewer than internal functions in the LaTeX kernel.

Just to make an example, \parbox is defined in terms of

\@iparbox \@iiparbox \@iiiparbox \@parboxto

the last one being redefined each time \parbox is called. Each of the first three internal functions has a different parameter text and it's quite difficult to read the code.

Perhaps the example is misleading, but expl3 was born to get rid of such difficulties by first providing a layer for “normalizing” arguments and then a clearer interface for internal functions.

In expl3 style we'd have

\NewDocumentCommand{\parbox}{O{c}oomm}
 {
  \innerlevel_parbox:nnnnn {...}
 }

that passes the arguments to an internal function with five arguments, as clearly specified by the function's signature.

The signature is what comes after the colon that should always appear in the name of an expl3 function.

For instance, \innerlevel_parbox:nnnnn would be defined with

\cs_new_protected:Nn \innerlevel_parbox:nnnnn { ... }

where ... stands for code using the five arguments. An alternative way would be

\cs_new_protected:Npn \outerlevel_parbox:nnnnn #1#2#3#4#5 { ... }

but I find that the former way is simpler and doesn't require code bits that can be deduced from the function's signature. On the other hand, the latter version is slightly more efficient.

You see that already \cs_new_protected:Nn has a signature itself, namely Nn. This tells the programmer that it should be followed by a single token (a control sequence, in this case) and then an argument in braces, neither of which is manipulated in any way.

After the definition, the programmer knows that \innerlevel_parbox:nnnnn should be followed by five arguments in braces.

Naming guidelines for the kernel functions also help in remembering what arguments a function will expect. For instance,

\hbox_set:Nn

expects a box variable as its first argument (a single unbraced token) and some text as the second argument. A more complex example is

\int_compare:nNnTF

but with some practice in expl3 programming one should be able to remember that the first argument should be an “integer denotation”, the second argument a comparator among <, = or > (single unbraced token), the third denotation another “integer denotation”, then two braced arguments for the code when the test is succesful or not, respectively.

You mention “manipulation” and this requires some explanation. One of the strong point of expl3 is the possibility of defining variants of functions.

With \cs_new(_protected):Nn we can only define functions whose signature only consists of N or n. But as soon as the function is defined, we can define variants thereof.

An example: \hbox_set:Nn is mostly similar to the user level function \sbox. But suppose you want to define a command that uses text stored in some macro, but using the current contents, to feed \sbox with. The legacy programming style would require

\expandafter\sbox\expandafter\mybox\expandafter{\container}

The analog with expl3 would look like

\hbox_set:NV \l_fluffy_my_box \l_fluffy_container_tl

after having done (just once, you do this at the outer level)

\cs_generate_variant:Nn \hbox_set:Nn { NV }

Thus the signature doesn't only tells the programmer how many arguments are expected: it also allows to modify how the function manipulates the arguments before the main function is called.

I dare you to write cleanly the code corresponding to \innerlevel_parbox:nnnnV. You can't do it with a bunch of \expandafter', but you'd need auxiliary function doing argument swapping in order to bring the fifth argument at the head, so \expandafter can be effectively used. Instead, the expl3 kernel already has the infrastructure to cleanly perform the task, without the programmer needing to know how the magic happens.

egreg
  • 1,121,712
  • From your discussion one could use \cs_new_protected:Npn \myfunc #1#2#3#4#5 { ... } rather than \cs_new_protected:Npn \myfunc:nnnnn #1#2#3#4#5 { ... }. The new function \myfunc taking five arguments would not have Latex complain. – Veak Oct 01 '23 at 23:14
  • 1
    @Fluffy you could but then you would not be able to generate variants as latex would not be able to construct names for them, \cs_generate_variant:Nn \myfunc:nnnnn {eeeee} would generate \myfunc:eeeee which is a variant that expands all arguments before the call) – David Carlisle Oct 01 '23 at 23:24
  • Thank you for explaining what \cs_generate_variant:Nn does. – Veak Oct 02 '23 at 00:13