Una macro para comprobar la capacidad de expansión del comando

Una macro para comprobar la capacidad de expansión del comando

me gustaria crearun comando que comprueba si una expresión es completamente expandible y falla si no(idealmente imprimiendo un mensaje de error). Me gustaría hacer esosin un motor TeX específico en mente. Creo que está relacionado con esta pregunta.Compruebe si la macro es completamente expandible, pero la respuesta proporcionada requiere LuaTeX.


código de prueba

Un código de prueba se vería así:

\documentclass[preview = true, varwidth = true]{standalone}
\usepackage{xparse}
\usepackage{xstring}

\NewDocumentCommand{\checkexpandability}{m}{
    % CODE HERE
}

\newcommand{\expandable}[1]{#1}
\newcommand{\notexpandable}[1]{%
    \edef\myvariable{\expandable{#1}}%
    \myvariable%
}

\begin{document}
\checkexpandability{\expandable{test}} % Should be OK
\checkexpandability{\notexpandable{test}} % Should CRASH
\checkexpandability{\IfBeginWith{string}{str}{true}{false}} % Should CRASH
\end{document}

En caso de que sea demasiado complicado

Si no es factible, entonces puedo modificar la firma del comando para incluir un parámetro que es a lo que el comando debería expandirse:

\begin{document}
\checkexpandability{\expandable{test}}{test} % Should be OK
\checkexpandability{\notexpandable{test}}{test} % Should CRASH
\checkexpandability{\IfBeginWith{string}{str}{true}{false}}{true} % Should CRASH
\end{document}

Comentar sobre la capacidad de expansión

Dado que la definición de totalmente expandible no es tan clara como uno podría pensar (ver el comentario a continuación), el contexto de esta pregunta es que solo estoy tratando de crear algo que me ayude a depurar algún código. Puedo limitar la pregunta a este comportamiento específico: si la macro funcionaría en las macros de contexto como el \colorcomando:

\documentclass[preview = true, varwidth = true]{standalone}
\usepackage{xcolor}

\newcommand{\expandable}[1]{#1}
\newcommand{\notexpandable}[1]{%
    \edef\myvariable{\expandable{#1}}%
    \myvariable%
}
    
\begin{document}
\color{\expandable{blue}} % OK
\color{\notexpandable{red}} % CRASHES
X
\end{document}

Básicamente, el \colorcomando hace el tipo de trabajo que estoy buscando, sólo que me gustaría llamarlo \checkexpandability, ser un poco más genérico e imprimir un bonito mensaje de error.

Respuesta1

Creo que el malentendido básico es

Básicamente, el \colorcomando hace el tipo de trabajo que estoy buscando,

El \colorcomando no realiza comprobaciones del tipo solicitado, simplemente espera que después de la expansión el argumento sea un nombre de color definido. Si la expansión falla, obtiene un error de bajo nivel o si se expande a un color indefinido, obtiene un mensaje de error específico, pero ninguna parte del procesamiento es genérica ni se aplica a un comando que no sea los comandos que esperan colores.

La única versión que podría implementarse es la versión con una expansión esperada, ya que simplemente pregunta si los dos argumentos son iguales después de la expansión. La capa de programación L3 tiene varias variantes de eso o puede usar el ifthenpaquete y

\ifthenelse{\equal{\expandable{test}}{test}}{yes}{no}

que devolverá sí si los argumentos se expanden a lo mismo, no si no lo hacen, o dará un error de bajo nivel si el argumento no es seguro en un contexto de expansión (que es lo que generalmente se entiende por "no es expandible")

Respuesta2

Para depurar su código, simplemente usaría \typeout.

\documentclass[preview = true, varwidth = true]{standalone}
\usepackage{xcolor}

\newcommand{\expandable}[1]{#1}
\newcommand{\notexpandable}[1]{%
    \edef\myvariable{\expandable{#1}}%
    \myvariable%
}
    
\begin{document}
\typeout{\expandable{blue}} % OK, print "blue"
\typeout{\notexpandable{red}} % CRASHES
X
\end{document}

El punto es que \typeoutexpandirá completamente su argumento y luego imprimirá el resultado completamente expandido en la terminal, para que pueda echar un vistazo a la terminal.

Para el primer caso se imprime blue, así que todo está bien. En el segundo caso, falla.


Por supuesto, hay dos problemas con el enfoque anterior.

  • Incluso si\expandable{blue} esTotalmente ampliable (lo que sea que signifique),Puede que no sea el caso que \colorgarantice expandir completamente su argumento antes de interpretar el resultado como un color.. (supongo que porley de hyrumSin embargo, prácticamente sería evitar romper "paquetes existentes).

    Entonces, si quieres estar más seguro, es mejor expandirlo por adelantado usando, por ejemplo,\ExpandArgs.

  • La información sobre el código de categoría, así como cualquier carácter especial escondido en el código (por ejemplo, espacio o tabulación), se pierde.

    En la práctica esto no importaría mucho, pero a veces sí importa. (por ejemplo, cuando intenta depurar algún paquete que intenta capturar el cuerpo del entorno palabra por palabra)

    Si ese es el caso, considere probarmi paquete. (El código es un desastre en este momento, pero funciona bien, y hay paquetes con peor código fuente por ahí)

información relacionada