Don't confuse \protect
with \protected
.
The latter is a primitive prefix for \def
\gdef
\edef
\xdef
and announces TeX that the defined control sequence (or active character) should behave in e
-expansion or x
-expansion as if it were prefixed by \noexpand
.
e
-expansion is used in the replacement text passed to \edef
or \xdef
and in the argument to \expanded
or \write
.
For instance,
\def\AAA{xyz}
\expanded{\noexpand\AAA}
\protected\def\BBB{xyz}
\expanded{\BBB}
would produce \AAA
and \BBB
respectively; macro expansion will take place later, following the usual rules.
Why is \protected
important? The above silly examples don't tell us. Suppose you want to write some text out to an auxiliary file to be \input
later. In the text you want to write out there is the control sequence \foo
that you don't want to be expanded when \write
is carried out, but only when you \input
the file.
The traditional way would be
\def\foo{}% initialize
\newwrite\outstream=myauxfile
\begingroup\let\foo\relax
\write\outstream{some text with \foo}
\endgroup
\def\foo{Useful definition}
\input myauxfile
which works because \relax
is unexpandable and so \foo
will be written out as \foo
. You need no \let
if you do instead
\protected\def\foo{}% initialize
\newwrite\outstream=myauxfile
\write\outstream{some text with \foo}
\endgroup
\def\foo{Useful definition}
\input myauxfile
(maybe again using \protected
when you redefine \foo
, depending on the actual job you want to do).
To the contrary, \protect
is not a primitive. It's a control sequence whose meaning changes depending on the context. In the earliest version of LaTeX you could find
\def\LaTeX{\protect\pLaTeX}
\def\pLaTeX{<the actual code for the logo>}
So if \LaTeX
was found during typesetting, \protect
would do nothing. But when \LaTeX
was found in the argument to \protected@edef
or \protected@write
(wrappers for \edef
and \write
), the meaning of \protect
would change to \noexpand
(this is the basic idea, the actual implementation is a bit more complex) and so when the underlying \edef
or \write
commands are executed, \pLaTeX
would remain.
Nowadays there is no explicit double definition with the p
prefix, but the idea remains the same. Robusted commands are defined with \DeclareRobustCommand
so that
\DeclareRobustCommand{\foo}{something}
is the same as
\expandafter\def\expandafter\foo\expandafter{%
\expandafter\protect\csname foo \endcsname
}
\expandafter\def\csname foo \endcsname{something}
so instead of \pfoo
like in the older way, a command \foo
(with a trailing space in the name) is defined. This way, the written out file would show \foo
(with two spaces), but this is unimportant when the file is \input
.
How does f
-expansion work? It exploits a slick feature of TeX (that can bite if you're not careful): when TeX is looking for an explicit <number>
, it performs macro expansion until finding a space token or an unexpandable token that cannot be interpreted as providing a <number>
under the current radix. The radix can be 10, 8, 16 or “alphabetic”. The rules are not difficult:
- an explicit number can begin with any number of
-
or +
tokens
- a radix designation may follow and can be a backquote
`
, a straight quote '
or a double straight quote "
- no radix designation means base ten
- the straight quote and the double straight quote mean octal and hexadecimal respectively
- the backquote means “alphabetical” constant
- digits, depending on the specified radix
An alphabetic constant is either a single character token or a control sequence of length one, such as \Q
. The trick used by f
-expansion is that macro expansion is done also after an alphabetic constant and the idea is that
\romannumeral-`\Q\foo
will expand \foo
before typesetting the result of \romannumeral-`\Q
(which is empty because the <number>
is negative). However, when doing this, the status of \foo
with respect to \protected
is ignored. Thus, using expl3
lingo, the following will produce different results:
\cs_new_protected:Nn \aad_foo: {abc}
\cs_new_protected:Nx \aad_foo_a: { \aad_foo: }
\exp_args:NNf \cs_new_protected:Nn \aad_foo_b: { \aad_foo: }
Indeed, if you try \cs_show:N \aad_foo_a:
and \cs_show:N
\aad_foo_b:` you will get respectively
> \aad_foo_a:=\protected\long macro:->\aad_foo: .
> \aad_foo_b:=\protected\long macro:->abc.
The similar situation is in c
-expansion, when TeX is trying to build a control sequence via \csname
. In this case it's obvious to ignore \protected
, because only character tokens should remain. Maybe the authors of e-TeX could have decided that in the context of c
-expansion a \protected
macro would get prefixed by \string
; they didn't.
\protected
c
andf
is pretty weird anyway and largely replaced bye
now the tex engines have been extended with an\expanded
primitive.\protected
mean in ac
-type expansion? Simply leaving macro names there doesn't really 'work'. For active chars, we are moving toward a setup that uses\ifincsname
to produce 'the char itself' in those contexts, but that's done in the definitions of the actives (and therefore is not dependent onexpl3
-specific code)