Entendiendo \@firstofone

Entendiendo \@firstofone

Estaba revisando esta respuesta y tratando de entender el código, soy un súper novato (mi segundo día) en LaTeX y me quedé atascado en la siguiente parte del código que no podía hacer que funcionara en un entorno sin tabla. Aquí está la forma más simple de lo que no entiendo.

\documentclass{article}
\begin{document}
    \newcommand*\f[3]{#1-#2-#3}
    \newcommand*\ex[1]{\f#1 - \expandafter\f\@firstofone}
     Try \ex{111}{221}
\end{document}

Por alguna razón, que no me queda clara, en el código vinculado, el último argumento no se consume, pero la construcción lo deja consumir expandafter\f\.... Por lo que tengo entendido, \expandafterprimero debería "ejecutarse" \@firstofone, obtener el {221}argumento, quitar los corchetes y enviarlo a \f. Esto no sucede y no puedo entender por qué.

Respuesta1

Necesitas usar \makeatletterpara que esto funcione, pero es lo de menos.

La convocatoria \ex{111}{221}se expande primero a

\f 111 - \expandafter\f\@firstofone{221}

Ahora \festá expandido y busca tres argumentos, encontrando 1y 1, 1porque TeX usa un solo token si falta una llave.

Por la definición de \festo se expande y el texto de reemplazo se reinserta en el flujo de entrada:

1-1-1 - \expandafter\f\@firstofone{221}

Los tokens 1-1-1 -no son ampliables y por eso se envían a la siguiente etapa. ahora queda

\expandafter\f\@firstofone{221}

Esto dejará \fde lado y expandirá \@firstofonelo que simplemente devuelve su (argumento sin refuerzos), por lo que obtenemos

\f221

eso se convierte en 2-2-1. Por lo tanto, el efecto neto de su código es imprimir

1-1-1 - 2-2-1

lo cual no parece realmente útil. Dondequiera que lo hayas encontrado, no confíes en él.

Respuesta2

Como señaló egreg en su respuesta, el uso de \@firstofoneno es muy útil y no hace una diferencia en este caso particular. Sin embargo, hay casos en los queesútil. Para completar, me gustaría dar dos ejemplos.

Macros ampliables

En¿Por qué el \expandafter\@firstoftwomodismo?Se proporciona un caso de uso típico para \@firstoftwoy en macros totalmente expandibles. , una especie de "función de identidad" de LaTeX, es útil en contextos similares donde solo se debe manejar un único parámetro:\@secondoftwo\@firstofone

\def\gobbleIfZero#1{%
  \ifnum#1=0
    \expandafter\@gobble
  \else
    \expandafter\@firstofone
  \fi
}

foo\gobbleIfZero{0}{bar}

foo\gobbleIfZero{123}{bar}

daré

foo

Foobar

\@gobble(como \@firstofone) toma un solo parámetro pero lo descarta y se expande a "nada".

Fijación de códigos cat

Un poco más complicado pero también más interesante es el caso en el que están involucrados cambios de código cat. Cuando TeX analiza argumentos para macros, corrige códigos cat cada vez que se lee el texto del argumento. Esto no importa en su caso ya que aquí no hay cambios en los códigos cat. Pero supongamos que se da el siguiente ejemplo algo artificial:

\begingroup
\catcode`4=\active
\gdef 4{four}
\endgroup

\newcommand*\f{\catcode`4=\active}
\newcommand*\exA{\f}
\newcommand*\exB{\expandafter\f\@firstofone}

{\exA{345}--{345}}

{\exB{345}--{345}}

Esto resulta en

3cuatro5-3cuatro5

345-3cuatro5

Las primeras cuatro líneas definen una macro global 4que se expande a four. Generalmente 4tiene catcode 12 (otro), por lo que lo cambiamos a 13 (activo) para poder crear una macro con él. \faquí devuelve estas macros al alcance cuando se ejecuta.

Cuando \exAse ejecuta, el código cat 4se cambia a 13, lo que luego hace que 4se expanda fouren los dos grupos siguientes. Aquí no hay ningún parámetro, por lo que esto es sencillo.

Por otro lado, en la macro se procesa \exBla primera parte , la cual simplemente devuelve el mismo texto,{345}\@firstofonepero arregla el catcodede 4a 12. Una vez que se soluciona, ¡ya no se puede cambiar! Aunque \fse procesa el cambio de catcodeantesel primero 345, no tendrá ningún efecto sobre él. Como los catcodes del segundo {345}aún no se han solucionado, los cambios seguirán aplicándose a este grupo.

Este comportamiento resulta muy útil si desea inyectar código adicional en macros existentes que se ocupan de cambios de código cat, por ejemplo \verb(inspirado enesta perla de TeX):

\begingroup
\catcode`\/\active
\catcode`\_\active
\@firstofone{%
  \verb|%
  \catcode`\/\active \def/{\par}%
  \catcode`\_\active \def_#1_{\textcolor{blue}{#1}}%
}_\documentclass_{article}/_\begin_{document}/  We all love _\LaTeX_!/_\end_{document}|
\endgroup

que salidas

producción

No sé dónde leíste \@firstofoneen primer lugar, pero podría haber sido en uno de estos contextos.

información relacionada