Multiletter-control-sequences in the .tex-input intended to yield a single ⟨control-word-token⟩ during tokenization are to consist of a single character of category 0(escape) trailed by a (non-empty) sequence of characters of category 11(letter).
Characters that represent decimal digits (0
, 1
, 2
, 3
, 4
, 5
, 6
, 7
, 8
, 9
) usually are assigned category 12(other). Therefore digits usually are not considered parts of names of ⟨control-word-tokens⟩ that come into being directly via tokenizing .tex-input. (⟨control-word-tokens⟩ coming into being as the result of the toplevel-expansion of \csname...\endcsname
is a different story.)
Why at all having TeX distinguish a set of category 11(letter)-characters from a set of category 12(other)-characters instead of having TeX just "look" at the union of these two sets?
TeXbook, Appendix B: Basic Control Sequences says:
When INITEX begins, category 12 (other) has been assigned to all 256
possible characters, except that the 52 letters A...Z and a...z are
category 11 (letter), and a few other assignments equivalent to the
following have been made:
\catcode `\\ =0 \catcode`\ =10 \catcode `\% =14
\catcode`\^^@=9 \catcode`\^^M=5 \catcode`\^^?=15
A double-dangerous-bend-paragraph of Chapter 7, How TeX reads what you type, says the same. Chapter 7 also says that token-producing-"operations" like \string
, \number
, \romannumeral
produce character-tokens of category 12(other). The same is for \the
in many situations.
To me it seems that category 12(other) is seen as the "standard".
To me it seems category 11(letter) was introduced for denoting (besides characters of category 0-10 and 13-15) another set of "non-standard"-characters. A set of "non-standard"-characters whose properties deviate from the properties of all other characters in the aspect that only these characters can be used within .tex-input for denoting names of ⟨control-word-tokens⟩.
I don't know why Professor Knuth decided for introducing a category for explicitly declaring a set of characters that can be used for denoting names of ⟨control-word-tokens⟩.
But I think having such a set of characters defined can be very handy. E.g., for more easily judging whether a sequence of characters forms the name of a ⟨control-word-token⟩ when looking at a piece of TeX-code with one's eyes.
However, I think that the fact that digit-characters by default are not elements of this set and therefore usually are not considered parts of names of ⟨control-word-tokens⟩ that come into being directly via tokenizing .tex-input is not due to a strong desire to specifically prevent/forbid/dis-allow the usage of digits in names of ⟨control-word-tokens⟩.
I suppose digit-characters by default usually not being considered parts of names of ⟨control-word-tokens⟩ that come into being directly via tokenizing .tex-input is just a side-effect taken for acceptable.
I suppose the main reason for assigning category 12(other) to digits (and this way—as a "side-effect"—excluding digits from that set of characters that can be used for denoting names of ⟨control-word-tokens⟩) is:
According to TeXbook, Chapter 24: Summary of Vertical Mode ⟨digit⟩-quantities are explicit character-tokens of catcode 12(other)012|112|212|312|412|512|612|712|812|912
(not catcode 11(letter)! ).
E.g., within macro-definitions a macro-argument is denoted by a category 6(parameter)-character-token that is trailed by such a (category-12-)⟨digit⟩-quantity in range 1..9:
\catcode`\1=11
\def\foo#1{this is foo}
\bye
yields an error-message "! Parameters must be numbered consecutively
."
Assigning category 12(other) to digits makes it possible to use them as ⟨digit⟩-quantities, e.g, for denoting macro-arguments or as components of ⟨(8-bit) number⟩-quantities. (⟨8-bit number⟩-quantities are a special case of ⟨number⟩-quantities and they are used with things like \catcode
).
Using characters/digits 0 ,1, ..., 9 as ⟨digit⟩-quantities is not possible if they have category 11(letter).
So a sort of reason why you usually cannot use 0, 1, ..., 9 in command names is that assigning them category 11(letter), which is the only way of making it possible to use them in command names, excludes using them as ⟨digit⟩-quantities, e.g., in macro-arguments #1
, #2
, etc, or as components of ⟨number⟩-quantities as ⟨digit⟩-quantities by design must be of category 12(other). Token-producing routines like \the⟨count-register⟩
and \number
and \string
all also produce character-tokens of category 12(other). (Exception: Spaces produced by \string
are of category 10.)
I said "a sort of reason" because, given how TeX is implemented, this just explains why switching digits to category 11(letter)—and this way allowing them to be components of the names of control-word-tokens—might cause problems/is not a good idea and why this this is not done by default. But this is not an explanation why TeX is implemented in a way where switching digits to category 11(letter)—and this way allowing them to be components of the names of control-word-tokens—can lead to problems.
Probably it would have been nice to allow ⟨digit⟩-quantities to be not only of category 12(other) but to be of category 11 also and to assign digits to category 11(letter) by default. But that ship has sailed—e.g., when denoting numbers of registers people in their .tex-input-files omit the space between \count
/\box
/\toks
/\skip
and the digit-sequence that denotes the number.
As under normal category code régime you cannot obtain the ⟨control-word-tokens⟩ \var1
and \var2
directly by having TeX read and tokenize .tex-input and as correct invocation of \csname..\endcsname
in combination with \expandafter
sometimes seems cumbersome, I offer a macro \CsNameToCsToken
to create, e.g., the ⟨control-word-token⟩ \var1
from the ⟨character-token⟩-sequence v11a11r11112
or the ⟨control-word-token⟩ \var2
from the ⟨character-token⟩-sequence v11a11r11212
.
The phrase "create the ⟨control-word-token⟩" here doesn't focus that much on defining a macro. The focus is more on the stage of expanding the macro \CsNameToCsToken
and hereby replacing ⟨character-tokens⟩ nested between curly-brace-tokens ({1
and }2
) by a ⟨control-word-token⟩—be that ⟨control-word-token⟩ defined or not (yet) defined.
\CsNameToCsToken
does things like \csname..\endcsname
for you and is intended to prevent you from the need of inserting \expandafter
and the like in the right places which can be tricky or—depending on your attitude and level of knowledge—painful. It is not a means for directly writing \var1
or \var2
within the .tex-input.
Syntax:
\CsNameToCsToken⟨stuff not in braces⟩{⟨NameOfCs⟩}
→
⟨stuff not in braces⟩\NameOfCs
(⟨stuff not in braces⟩
may be empty.)
(⟨stuff not in braces⟩
is treated as {
-delimited argument via TeX's #{
-notation.
Due to \romannumeral
-expansion the result is obtained by triggering two expansion-steps, e.g., by having two "hits" with \expandafter
.)
Examples:
With such a macro you are not bound to specific definition commands:
\CsNameToCsToken{foo}
→ \foo
.
\CsNameToCsToken\global\long\outer\def{foo}
→ \global\long\outer\def\foo
.
\CsNameToCsToken\expandafter{foo}\bar
→ \expandafter\foo\bar
.
\CsNameToCsToken\let{foo}=\bar
→ \let\foo=\bar
.
\CsNameToCsToken\CsNameToCsToken\let{foo}={bar}
→ \CsNameToCsToken\let\foo={bar}
→ \let\foo=\bar
.
\CsNameToCsToken\string{foo}
→ \string\foo
.
\CsNameToCsToken\meaning{foo}
→ \meaning\foo
.
\CsNameToCsToken
might be useful not only with plain TeX. It can as well be applied with LaTeX 2ε- and xparse
-definition-commands:
\CsNameToCsToken\newcommand{foo}
→ \newcommand\foo
.
\CsNameToCsToken\DeclareRobustCommand{foo}
→ \DeclareRobustCommand\foo
.
\CsNameToCsToken\NewDocumentCommand{foo}...
→ \NewDocumentCommand\foo...
.
Using plain TeX, not LaTeX:
\begingroup
\def\foo#1{#1}%
\catcode`\@=11
\foo{%
\endgroup
%%===============================================================================
%% End \romannumeral-driven expansion safely:
%%===============================================================================
\chardef\UD@stopromannumeral=`\^^00
%%===============================================================================
%% Obtain control sequence token from name of control sequence token:
%%===============================================================================
%% \CsNameToCsToken<stuff not in braces>{NameOfCs}
%% -> <stuff not in braces>\NameOfCs
%% (<stuff not in braces> may be empty.)
\long\def\CsNameToCsToken#1#{\romannumeral\InnerCsNameToCsToken{#1}}%
\long\def\InnerCsNameToCsToken#1#2{%
\expandafter\UD@exchange\expandafter{\csname#2\endcsname}{\UD@stopromannumeral#1}%
}%
\long\def\UD@exchange#1#2{#2#1}%
}%
\begingroup\tt
\noindent Define \string\var1:
\hfill\break
\string\CsNameToCsToken\string\def\string{var1\string}\string{This is the current value of var1.\string}
\endgroup
\CsNameToCsToken\def{var1}{This is the current value of var1.}
\hfill\break\null
\begingroup\tt
\noindent Define \string\var2:
\hfill\break
\string\CsNameToCsToken\string\def\string{var2\string}\string{This is the current value of var2.\string}
\endgroup
\CsNameToCsToken\def{var2}{This is the current value of var2.}
\hfill\break\null
\begingroup\tt
\noindent Using \string\var1/var1: \string\CsNameToCsToken\string{var1\string}
\hfill\break\null\hfill\break\null
\endgroup
\noindent \CsNameToCsToken{var1}
\hfill\break\null
\begingroup\tt
\noindent Using \string\var2/var2: \string\CsNameToCsToken\string{var2\string}
\hfill\break\null\hfill\break\null
\endgroup
\noindent \CsNameToCsToken{var2}
\bye
Using LaTeX:
\makeatletter
%%===============================================================================
%% End \romannumeral-driven expansion safely:
%%===============================================================================
\@ifdefinable\UD@stopromannumeral{\chardef\UD@stopromannumeral=`\^^00}%
%%===============================================================================
%% Obtain control sequence token from name of control sequence token:
%%===============================================================================
%% \CsNameToCsToken<stuff not in braces>{NameOfCs}
%% -> <stuff not in braces>\NameOfCs
%% (<stuff not in braces> may be empty.)
\@ifdefinable\CsNameToCsToken{%
\long\def\CsNameToCsToken#1#{\romannumeral\InnerCsNameToCsToken{#1}}%
}%
\newcommand\InnerCsNameToCsToken[2]{%
\expandafter\UD@exchange\expandafter{\csname#2\endcsname}{\UD@stopromannumeral#1}%
}%
\newcommand\UD@exchange[2]{#2#1}%
\makeatother
\documentclass{article}
\begin{document}
\begin{verbatim}
Define \var1:
\CsNameToCsToken\newcommand*{var1}{This is the current value of var1.}
\end{verbatim}
\CsNameToCsToken\newcommand*{var1}{This is the current value of var1.}
\begin{verbatim}
Define \var2:
\CsNameToCsToken\newcommand*{var2}{This is the current value of var2.}
\end{verbatim}
\CsNameToCsToken\newcommand*{var2}{This is the current value of var2.}
\begin{verbatim}
Using \var1/var1: \CsNameToCsToken{var1}
\end{verbatim}
\CsNameToCsToken{var1}
\begin{verbatim}
Using \var2/var2: \CsNameToCsToken{var2}
\end{verbatim}
\CsNameToCsToken{var2}
\end{document}