Referencia circular en macro LaTeX

Referencia circular en macro LaTeX

Mientras intentaba aprender macros en LaTeX, me encontréesta definición:

\x@protectEs una macro con un argumento, representado por " #1". \@typeset@protecttambién se define como y por lo tanto se ejecuta \relaxla primera rama del , que no hace nada. \ifx( \ifxcompara el significado de dos macros). Entonces, el único resultado de \x@protectes que su argumento, el primer " \\" en la definición de \\, se descarta. Esto deja el comando \protect, que no requiere operación, y \\a sí mismo. Esta parece ser una definición circular. De hecho, no lo es. Es un truco desagradable por parte de los autores de LaTeX que intentan cubrir sus huellas. Eche una segunda mirada, sumamente sospechosa, a la lista de \\. Hay dos espacios entre el último " \\" y el punto, mientras que después de la última secuencia de control en otros listados, ¡solo hay uno! De hecho, sólo hay un espacio final en todos los listados. El penúltimo espacio en el listado de \\es parte del nombre de su última secuencia de control, que es " \\", ¡incluido el espacio!`

¿Por qué la referencia circular?

¿Por qué no se estropea al encontrar una referencia circular?

Respuesta1

Comencemos una sesión interactiva con ¿ pdflatex testdónde test.texestá?

\documentclass{article}

\DeclareRobustCommand{\?}{js bibra}

\makeatletter

\show\?

El \showcomando detendrá la ejecución, por lo que podremos emitir más comandos.

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\?

¿Qué pasa cuando \?se procesa? Hay dos casos: si \protectno tiene el mismo significado que \@typeset@protect(que es \relax), entonces se sigue la rama falsa. Por lo tanto, el flujo de entrada tendrá

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

y la expansión de \@x@protecteliminará las dos últimas fichas, dejándolas \protect\?\fi(y \fieventualmente desaparecerán).

Esto sucede, por ejemplo, en \protected@edefo \protected@write, cuando \protectse le asigna un significado diferente al de \@typeset@protect.

Si es así, el condicional es verdadero, por lo que el flujo de entrada tendrá, después de omitir la rama falsa,

\protect\?

Ahora \protectdesaparece y nosotrosparecerestar en el mismo lugar que antes. Pero no lo somos, porque el siguiente token \protectesdiferentea partir de \?eso se ingresó en el documento de prueba.

Mire de cerca el resultado del primer \showcomando. Obtenemos

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

Entre ->y el punto final, TeX representa el texto de reemplazo de la macro. Las reglas para esta representación son que las palabras de control van seguidas de un espacio, mientras que los símbolos de control no. Esto explica el espacio después \x@protecty \protectla ausencia de espacio después \?. Pero el período final está precedido pordosespacios! ¿De dónde vienen?

Cuando lo haces \DeclareRobustCommand{\?}{js bibra}, LaTeX hace varias cosas, la principal es algo como

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

y luego usar esta macro con un nombre muy no estándar para definir la "versión de nivel de usuario" de \?. Tenga en cuenta el espacio antes de \endcsname, que termina en el nombre de la macro.

Hay algunos detalles más, pero la idea es facilitar la escritura de archivos auxiliares. En las versiones anteriores de LaTeX, vimos algo como

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

Cuando se lanzó LaTeX2e, el código anterior pasó a ser

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

explotando un nuevo nivel de abstracción. En las versiones anteriores, \LaTeX{}en el título de una sección se habría escrito

\protect\pLaTeX {}

en los archivos auxiliares. Ahora escribe

\LaTeX  {}

debido al espacio final en el nombre y la regla. El doble espacio se ignorará cuando se lea el archivo auxiliar.

Es ligeramente diferente para símbolos de control como \\o \?, pero la idea general es la misma.

información relacionada