
Encontrei um uso aparentemente idiomático em \pgf@marshal
todo o pacote PGF e me pergunto por que ele é usado.
Por exemplo de pgflibraryshapes.gates.logic.US.code.tex
:
{%
\edef\pgf@marshal{%
\noexpand\pgfpatharc{90}{-90}{\the\pgf@yc}%
}%
\pgf@marshal%
}
Esta é provavelmente fácil, mas por que não apenas
\pgfpatharc{90}{-90}{\the\pgf@yc}
?
Responder1
Embora \pgfpatharc
não seja usado \pgf@yc
(pelo menos não até que já tenha sido avaliado e armazenado em outro lugar) e seria seguro fazê-lo
\pgfpatharc{90}{-90}{\pgf@yc}
(sem o \the
par), oo próprio manual avisa
Atenção:O PGF usa esses registradores para realizar operações de caminho. Por razões de eficiência, os comandos de caminho nem sempre os protegem. Como consequência, o código
\pgfpointadd{\pgfpoint{\pgf@xa}{\pgf@ya}}{\pgfpoint{\pgf@xb}{\pgf@yb}}
pode falhar: Dentro de
\pgfpointadd
, os\pgf@xa
registros e amigo podem ser modificados. Em particular, pode acontecer que\pgf@xb
seja alterado antes de\pgfpoint{\pgf@xb}{\pgf@yb}
ser avaliado. O correto seria primeiro expandir tudo usando\edef
e depois processar os valores, resultando em operações caras e desnecessárias. Claro, pode-se evitar isso simplesmente olhando o código-fonte\pgfpointadd
para ver quais registradores são usados.
(Curiosamente, o exemplo dado realmente funcionaria, mas não
\pgfpointadd{\pgfpoint{\pgf@xb}{\pgf@yb}}{\pgfpoint{\pgf@xa}{\pgf@ya}}
porque as coordenadas do primeiro ponto serão armazenadas \pgf@xa
e \pgf@ya
posteriormente adicionadas às do segundo ponto.)
No caso de \pgfpatharc
, #3
é avaliado antes de \pgf@yc
ser usado e isso só acontece com escopo, então \pgf@yc
ainda tem o mesmo valor depois de \pgfpatharc
.
Então, sim, o desenvolvedor da biblioteca de circuitos poderia ter dado uma olhada na definição \pgfpatharc
e poderia ter determinado que não faz sentido.
Mas há outros pontos a serem considerados:
- O
\pgfpatharc
comando pode ter funcionado de forma diferente no momento em que a biblioteca de circuitos foi escrita. - O
\pgfpatharc
comando pode mudar no futuro. - O autor da biblioteca de circuitos em algum outro momento percebeu um conflito e alterou todas as chamadas de macro semelhantes para que nunca mais tivessem que lidar com tais problemas.
Responder2
Outra perspectiva para quem não está muito familiarizado com o modelo de execução do TeX.
Wikcionário:
marechal (verbo)
4. Reunir dados para transmissão.
5. (computação, transitivo) Para serializar um objeto em um estado empacotado representado por uma sequência de bytes que pode posteriormente ser convertido novamente em um objeto com propriedades equivalentes.
Embora no contexto da computação geralmente o significado 5 seja desejado, neste caso o significado 4 parece ser mais relevante. Mas também pode ser entendido como "serializar o código em uma lista de tokens e, posteriormente, executar a lista de tokens como um código" --- mas, no TeX, código e lista de tokens são basicamente a mesma coisa.
dr:
Por padrão, os comandos do TeX são executados "de fora para dentro" --- isto é, diferentemente das linguagens de programa típicas onde os "argumentos de função" são "avaliados" antes de "serem passados para a função", no TeX, o argumento é passado para o macro textualmente.
- em Python
f(1+2)
ef(3)
é idêntico porque1+2
é avaliado3
antes def
recebê-lo. No TeX,\f{\numexpr 1+2\relax}
e\f{3}
não é idêntico.
- em Python
Neste caso, como explicado ema outra resposta, o chamador deseja avaliar o número antes de passar para a função.
O TeX possui um número muito limitado de mecanismos para manipular tokens. O código que você vê é equivalente a algo como
eval(r"\pgfpatharc{90}{-90}{" + pgfyc + "}")
na sintaxe Python --- o código é manipulado como uma lista de tokens e depois executado.
A alternativa seria adicionar
\expandafter
todos os lugares do código, o que é definitivamente menos eficiente. (há também\expanded{\unexpanded{...}}
, mas isso não existia no momento em que o código foi escrito.)Outros lugares em que esta expressão é usada podem ser vistos, por exemplocomo usar
pgfplots
plotagem em loopcom\edef\temp{...}\temp
.O prefixo
pgf@
indica que o nome da macro é interno ao pacote pgf. Se você não estiver editando o código-fonte do PGF/TikZ, você deve criar seu próprio nome e não reutilizá-lo\pgf@marshal
.