Uso idiomático de \pgf@marshal en PGF

Uso idiomático de \pgf@marshal en PGF

Me he encontrado con un uso aparentemente idiomático en \pgf@marshaltodo el paquete PGF y me pregunto por qué se usa.

Por ejemplo de pgflibraryshapes.gates.logic.US.code.tex:

{%
    \edef\pgf@marshal{%
        \noexpand\pgfpatharc{90}{-90}{\the\pgf@yc}%
    }%
    \pgf@marshal%
}

Probablemente sea fácil, pero ¿por qué no simplemente

\pgfpatharc{90}{-90}{\the\pgf@yc}

?

Respuesta1

Si bien \pgfpatharcno se usa \pgf@yc(al menos no hasta que ya haya sido evaluado y almacenado en otro lugar) y hubiera sido seguro hacerlo

\pgfpatharc{90}{-90}{\pgf@yc}

(sin el \thepar), elel propio manual advierte

Atención:PGF utiliza estos registros para realizar operaciones de ruta. Por razones de eficiencia, los comandos de ruta no siempre los protegen. En consecuencia, el código

\pgfpointadd{\pgfpoint{\pgf@xa}{\pgf@ya}}{\pgfpoint{\pgf@xb}{\pgf@yb}}

puede fallar: En el interior \pgfpointadd, los \pgf@xaregistros de amigos y pueden modificarse. En particular, puede ocurrir que \pgf@xbse modifique antes de \pgfpoint{\pgf@xb}{\pgf@yb}ser evaluado. Lo correcto sería expandir primero todo usando \edefy luego procesar los valores, lo que resultaría en operaciones costosas e innecesarias. Por supuesto, esto se puede evitar simplemente mirando el código fuente de \pgfpointaddpara ver qué registros se utilizan.

(Curiosamente, el ejemplo dado realmente funcionaría, pero no

\pgfpointadd{\pgfpoint{\pgf@xb}{\pgf@yb}}{\pgfpoint{\pgf@xa}{\pgf@ya}}

porque las coordenadas del primer punto se almacenarán \pgf@xay \pgf@yaluego se agregarán a las del segundo punto).

En el caso de \pgfpatharc, #3se evalúa antes de \pgf@ycusarse y esto solo sucede en el ámbito, por lo que \pgf@yctodavía tiene el mismo valor después \pgfpatharc.

Entonces, sí, el desarrollador de la biblioteca de circuitos podría haber examinado la definición de \pgfpatharcy podría haber determinado que no tiene sentido.

Pero hay otros puntos a considerar:

  • Es posible que el \pgfpatharccomando haya funcionado de manera diferente al momento de escribir la biblioteca de circuitos.
  • El \pgfpatharccomando podría cambiar en el futuro.
  • En algún otro momento, el autor de la biblioteca de circuitos notó un conflicto y cambió todas las llamadas a macros similares para que nunca más tuvieran que lidiar con tales problemas.

Respuesta2

Otra perspectiva para aquellos que no están muy familiarizados con el modelo de ejecución TeX.


Wikcionario:

mariscal (verbo)
4. Recopilar datos para su transmisión.
5. (informática, transitiva) Para serializar un objeto en un estado ordenado representado por una secuencia de bytes que luego se puede convertir nuevamente en un objeto con propiedades equivalentes.

Mientras que en el contexto informático normalmente se desea el significado 5, en este caso el significado 4 parece ser más relevante. Pero también podría entenderse como "serializar el código en una lista de tokens y luego ejecutar la lista de tokens como un código" --- pero luego, en TeX, el código y la lista de tokens son prácticamente lo mismo.

tl;dr:

  • De forma predeterminada, los comandos TeX se ejecutan "de afuera hacia adentro", es decir, a diferencia de los lenguajes de programa típicos donde los "argumentos de función" se "evalúan" antes de "pasarse a la función", en TeX, el argumento se pasa al macro textualmente.

    • en Python, f(1+2)y f(3)es idéntico porque 1+2se evalúa 3antes de frecibirlo. En TeX, \f{\numexpr 1+2\relax}y \f{3}no es idéntico.
  • En este caso, como se explica enla otra respuesta, la persona que llama quiere evaluar el número antes de pasar a la función.

  • TeX tiene una cantidad muy limitada de mecanismos para manipular tokens. El código que ves es equivalente a algo como

    eval(r"\pgfpatharc{90}{-90}{" + pgfyc + "}")
    

    en la sintaxis de Python --- el código se manipula como una lista de tokens y luego se ejecuta.

    La alternativa sería agregar \expandafteren todas partes del código, lo que definitivamente es menos eficiente. (También existe \expanded{\unexpanded{...}}, pero no existía en el momento en que se escribió el código).

  • Otros lugares donde se usa este modismo se pueden ver, por ejemplocómo utilizarpgfplots la trama en un buclecon \edef\temp{...}\temp.

  • El prefijo pgf@indica que el nombre de la macro es interno del paquete pgf. Si no está editando el código fuente de PGF/TikZ, debe crear su propio nombre y no reutilizarlo \pgf@marshal.

información relacionada