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.
\foo:Nn
would be used as\foo:Nn \something {some tokens}
\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 whichLatex
extracts theArgument Specifier
. Correct ?