
Eu estava olhando essa resposta e tentando entender o código, sou um super novato (meu segundo dia) em LaTeX e fiquei preso na seguinte parte do código que não consegui fazê-lo funcionar em um ambiente que não fosse de tabela. Aqui está a forma mais simples do que não entendo.
\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 algum motivo, que não está claro para mim, no código vinculado, o último argumento não é consumido mas fica para ser consumido pela expandafter\f\...
construção. Pelo que entendi \expandafter
deveria primeiro "executar" \@firstofone
, pegando o {221}
argumento, tirando os colchetes e alimentando-o \f
. Isso não acontece e não consigo entender o porquê.
Responder1
Você precisa usar \makeatletter
para que isso funcione, mas é o mínimo.
A chamada \ex{111}{221}
se expande primeiro para
\f 111 - \expandafter\f\@firstofone{221}
Now \f
é expandido e procura três argumentos, encontrando 1
e 1
, 1
porque o TeX usa um único token se uma chave estiver faltando.
Pela definição, \f
isso é expandido e o texto de substituição é reinserido no fluxo de entrada:
1-1-1 - \expandafter\f\@firstofone{221}
Os tokens 1-1-1 -
não são expansíveis e por isso são enviados para a próxima etapa. Agora resta
\expandafter\f\@firstofone{221}
Isso irá deixar \f
de lado e expandir, \@firstofone
o que apenas retorna seu (argumento não apoiado), então obtemos
\f221
isso se torna 2-2-1
. Assim, o efeito líquido do seu código é imprimir
1-1-1 - 2-2-1
o que não parece realmente útil. Onde quer que você o tenha encontrado, não confie nele.
Responder2
Como egreg apontou em sua resposta, o uso de \@firstofone
não é muito útil e não faz diferença neste caso específico. Contudo, há casos em queéútil. Para completar, gostaria de dar dois exemplos.
Macros expansíveis
EmPor que o \expandafter\@firstoftwo
idioma?é fornecido um caso de uso típico para \@firstoftwo
e em macros totalmente expansíveis. , uma espécie de "função de identidade" do LaTeX, é útil em contextos semelhantes onde apenas um único parâmetro deve ser tratado:\@secondoftwo
\@firstofone
\def\gobbleIfZero#1{%
\ifnum#1=0
\expandafter\@gobble
\else
\expandafter\@firstofone
\fi
}
foo\gobbleIfZero{0}{bar}
foo\gobbleIfZero{123}{bar}
darei
foo
foobar
\@gobble
(como \@firstofone
) recebe um único parâmetro, mas o descarta e expande para "nada".
Correção de catcodes
Um pouco mais complicado, mas também mais interessante, é o caso em que estão envolvidas alterações no código de gato. Quando o TeX está analisando argumentos para macros, ele corrige catcodes sempre que o texto do argumento está sendo lido. Isso não importa no seu caso, pois não há alterações nos códigos de gato aqui. Mas suponha que o seguinte exemplo, um tanto artificial, seja dado:
\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}}
Isto resulta em
3quatro5-3quatro5
345-3quatro5
As primeiras quatro linhas definem uma macro global 4
que se expande para four
. Geralmente 4
tem catcode 12 (outro), então mudamos para 13 (ativo) para poder fazer dele uma macro. \f
aqui traz essas macros de volta ao escopo quando executadas.
Quando \exA
é executado, o catcode 4
é alterado para 13 que posteriormente faz 4
ser expandido para four
ambos os grupos seguintes. Não há parâmetros aqui, então isso é simples.
Por outro lado, na macro é processada \exB
a primeira parte pela qual apenas retorna o mesmo texto,{345}
\@firstofone
mas corrige o catcodede 4
a 12. Depois de corrigido, não poderá mais ser alterado! Mesmo que a mudança do catcode \f
seja processadaanteso primeiro 345
, não terá nenhum efeito sobre ele. Como os catcodes do segundo {345}
ainda não foram corrigidos, as alterações ainda serão aplicadas a este grupo.
Este comportamento é bastante útil se você deseja injetar código extra em macros existentes que lidam com alterações de catcode, por exemplo \verb
(inspirado poresta pérola 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
quais saídas
Não sei onde você leu sobre \@firstofone
isso, mas pode ter sido em um desses contextos.