LaTeX3 not enforcing argument types for user-defined control sequences, why

expl3latex3macros

From a previous question, @egreg's states:

The argument types N and n are the most common. The former means that the argument must be an unbraced single token, the latter means that the argument must be a braced list of tokens.

This is more or less clear to me, but it looks like the L3 interface does not enforce this for user-defined functions, here's an MWE:

\documentclass{article}

\begin{document}
    \ExplSyntaxOn
    \cs_new:Nn \myFunc:N {<<#1>>}
    \myFunc:N {test}
    \ExplSyntaxOff

\end{document}

The code above compiles fine, even if I am passing a braced list of tokens to function myFunc:N which is apparently declared to strictly take an unbraced single token.

This makes a big part of the L3 programming layer, i.e. function definitions and argument specifications seem like a mere syntactic convention. sigh.

Why are the argument types not enforced for user-defined functions as one would expect?

Colons

Strangely, the compiler does throw an error when I omit the colon :, for example if I declare a function myFunc as opposedto myFunc:N. So that seems to be enforced…

Best Answer

The programming layer expl3 is still based on the TeX language and the lookup for arguments is as defined by TeX's rules.

These rules only distinguish between delimited and undelimited arguments. And what expl3 calls “functions” are actually regular TeX macros; variables, depending on their type, can be either macros or registers.

The basic \cs_new:Nn function for defining other functions only deals with undelimited arguments. It takes two arguments: one a single token, which should be a valid name for a function including the signature; the second argument should be a braced list of tokens.

The signature is used in order to supply the correct parameter text for the underlying macro to be defined, because a declaration such as

\cs_new:Nn \mymodule_foo:nn { #1 -- #2 }

eventually becomes

\def\mymodule_foo:nn #1#2{#1--#2}

(just like \newcommand does). It is possible to define functions without a signature in their name, but it's generally not recommended: these would be user level commands and it's better to use \NewDocumentCommand for them.

On the other hand, if you do

\cs_new:Nn \mymodule_foo:N { --#1-- }

and then call

\mymodule_foo:N {text}

TeX will follow its own rules and accept the code without complaining, notwithstanding that the coding is wrong from the expl3 point of view.

Why is it not enforced that arguments are specified in the proper way as regards to braced or nonbraced? Because this would be generally impossible and, in any case, it would introduce a heavy overhead in terms of speed and efficiency.