1

While trying to learn macros in LaTeX, I came across this definition:

\x@protect is a macro with one argument, represented by the "#1". \@typeset@protect also is defined as \relax and therefore the first branch of the \ifx is executed, which does nothing. (\ifx compares the meaning of two macros.) So the only result of \x@protect is that its argument, the first "\\" in the definition of \\, is thrown away. This leaves the command \protect, which is a no-operation, and \\ itself. This seems to be a circular definition. In fact, it isn't. It is a nasty trick on the part of LaTeX's authors trying to cover their tracks. Have a second, exceedingly suspicious look at the listing of \\. There are two spaces between the last "\\" and the period, while after the last control sequence in other listings, there is only one! In fact there is only one trailing space in all listings. The last but one space in the listing of \\ is part of the name of its last control sequence, which is "\\ ", including the space!`

Why the circular reference?

Why doesn't it break down on encountering a circular reference?

6
  • This is a remnant of the pre-eTeX protection mechanism, where you would prefix things with \protect and use \protected@edef instead of plain \edef. The \protected@edef changes \protect into \noexpand temporarily. Otherwise \protect is just \relax. Nowadays you'd just use \DeclareRobustCommand but the LaTeX kernel strives for maximum compatibility, so old definitions won't be adjusted. – Henri Menke Dec 6 '19 at 1:49
  • 2
    The short answer to your question is that the reference isn't circular, as stated in the paragraph ("... This seems to be a circular definition. In fact, it isn't..."). – Werner Dec 6 '19 at 3:04
  • @HenriMenke \DeclareRobustCommand doesn't use etex \protect either. (in fact until this year nothing did by default) – David Carlisle Dec 6 '19 at 8:10
  • @DavidCarlisle I see. What is the LaTeX way for \protected\def then? – Henri Menke Dec 6 '19 at 8:27
  • 1
    @HenriMenke \protected\def or something with _ and : in its name. or \DeclareDocumentCommand from xparse – David Carlisle Dec 6 '19 at 8:27
4

Let's start an interactive session with pdflatex test, where test.tex is

\documentclass{article}

\DeclareRobustCommand{\?}{js bibra}

\makeatletter

\show\?

The \show command will stop the run, so we're able to issue more commands

This is pdfTeX, Version 3.14159265-2.6-1.40.20 (TeX Live 2019) (preloaded format=pdflatex)
 restricted \write18 enabled.
entering extended mode
(./test.tex
LaTeX2e <2019-10-01> patch level 3
(/usr/local/texlive/2019/texmf-dist/tex/latex/base/article.cls
Document Class: article 2019/10/25 v1.4k Standard LaTeX document class
(/usr/local/texlive/2019/texmf-dist/tex/latex/base/size10.clo))
> \?=macro:
->\x@protect \?\protect \?  .
l.7 \show\?

? i\show\x@protect
> \x@protect=macro:
#1->\ifx \protect \@typeset@protect \else \@x@protect #1\fi .
<insert>   \show\x@protect

l.7 \show\?

? i\show\@x@protect
> \@x@protect=macro:
#1\fi #2#3->\fi \protect #1.
<insert>   \show\@x@protect

l.7 \show\?

What happens when \? is processed? There are two cases: if \protect hasn't the same meaning as \@typeset@protect (which is \relax), then the false branch is followed. Thus the input stream will have

\@x@protect\?\fi\protect\?

and the expansion of \@x@protect will remove the last two tokens, leaving \protect\?\fi (and \fi will eventually disappear).

This happens, for instance, in \protected@edef or \protected@write, when \protect is assigned a different meaning than \@typeset@protect.

If it has, the conditional is true, so the input stream will have, after skipping the false branch,

\protect\?

Now \protect disappears and we seem to be in the same place as before. But we aren't, because the token following \protect is different from \? that was input in the test document.

Look closely at the output of the first \show command. We get

->\x@protect \?\protect \?  .

Between -> and the trailing period, TeX represents the replacement text of the macro. The rules for this representation are that control words are followed by a space, whereas control symbols aren't. This explains the space after \x@protect and \protect as well as no space after \?. But the trailing period is preceded by two spaces! Where do they come from?

When you do \DeclareRobustCommand{\?}{js bibra}, LaTeX does several things, the main one being something like

\expandafter\def\csname ? \endcsname{js bibra}

and then using this macro with a very nonstandard name for defining the “user level version” of \?. Note the space before \endcsname, which ends up in the macro name.

There are some more details, but the idea is to ease writing of auxiliary files. In the older versions of LaTeX, we saw something like

\def\LaTeX{\protect\pLaTeX}
\def\pLaTeX{<the real definition>}

When LaTeX2e was released, the previous code became

\DeclareRobustCommand{\LaTeX}{<the real definition>}

exploiting a new abstraction level. In the older versions, \LaTeX{} in a section title would have written

\protect\pLaTeX {}

in the auxiliary files. Now it writes out

\LaTeX  {}

because of the trailing space in the name and the rule. The double space will be ignored when the auxiliary file is read in.

It's slightly different for control symbols such as \\ or \?, but the general idea is the same.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.