Uso idiomático de \pgf@marshal em PGF

Uso idiomático de \pgf@marshal em PGF

Encontrei um uso aparentemente idiomático em \pgf@marshaltodo 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 \pgfpatharcnã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 \thepar), 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@xaregistros e amigo podem ser modificados. Em particular, pode acontecer que \pgf@xbseja alterado antes de \pgfpoint{\pgf@xb}{\pgf@yb}ser avaliado. O correto seria primeiro expandir tudo usando \edefe depois processar os valores, resultando em operações caras e desnecessárias. Claro, pode-se evitar isso simplesmente olhando o código-fonte \pgfpointaddpara 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@xae \pgf@yaposteriormente adicionadas às do segundo ponto.)

No caso de \pgfpatharc, #3é avaliado antes de \pgf@ycser usado e isso só acontece com escopo, então \pgf@ycainda tem o mesmo valor depois de \pgfpatharc.

Então, sim, o desenvolvedor da biblioteca de circuitos poderia ter dado uma olhada na definição \pgfpatharce poderia ter determinado que não faz sentido.

Mas há outros pontos a serem considerados:

  • O \pgfpatharccomando pode ter funcionado de forma diferente no momento em que a biblioteca de circuitos foi escrita.
  • O \pgfpatharccomando 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)e f(3)é idêntico porque 1+2é avaliado 3antes de frecebê-lo. No TeX, \f{\numexpr 1+2\relax}e \f{3}não é idêntico.
  • 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 \expandaftertodos 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 pgfplotsplotagem 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.

informação relacionada