Mientras trabajaba con glifos de sombrero personalizados usando la primera versión deesta solución, pdflatex
empezó a tardar mucho en compilar un documento. Esa respuesta vinculada señala que es una solución más lenta, pero inicialmente fue muy lenta, lo cual no importó. Luego se volvió tolerablemente lento después de usar dos sombreros apilados. Y después de que fui a investigar y apilé tres sombreros, todo se volvió eterno.
He aquí una razón resumida:
\documentclass[12pt, a4paper]{article}
\usepackage{scalerel}
\begin{document}
\ensuremath{
\ThisStyle{
\SavedStyle\ThisStyle{
\SavedStyle\ThisStyle{
\SavedStyle\ThisStyle{
\SavedStyle\ThisStyle{
\SavedStyle\ThisStyle{
\SavedStyle\ThisStyle{
\SavedStyle\ThisStyle{
\SavedStyle . }}}}}}}
}}
\end{document}
Esto tarda 15 segundos con pdflatex
o latex
. Si eliminamos un nivel de anidamiento, se reduce a 2 segundos, y si agregamos un nivel más que en el ejemplo, obtenemos 269 segundos.
Es evidente que está sucediendo algo exponencial. Mirando haciaescalarel.sty, el código para \SavedStyle
y \ThisStyle
es el siguiente:
\def\SavedStyle{\csname @mstyle\m@switch\endcsname}
\newcommand\ThisStyle[1]{%
\ifmmode%
\def\@mmode{T}\mathchoice%
{\edef\m@switch{D}\LMex=1ex\relax\LMpt=1pt\relax#1}%
{\edef\m@switch{T}\LMex=1ex\relax\LMpt=1pt\relax#1}%
{\edef\m@switch{S}\LMex=\scriptstyleScaleFactor ex\relax%
\LMpt=\scriptstyleScaleFactor pt\relax#1}%
{\edef\m@switch{s}\LMex=\scriptscriptstyleScaleFactor ex\relax%
\LMpt=\scriptscriptstyleScaleFactor pt\relax#1}%
\else%
\def\@mmode{F}%
\edef\m@switch{T}\LMex=1ex\relax\LMpt=1pt\relax#1%
\fi%
}
Mi conjetura es que el argumento \ThisStyle
se amplía cuatro veces en cada nivel. En otras palabras, \mathchoice
no es perezoso.
¿Hay alguna manera de sacar a #1
relucir esos \mathchoice
argumentos y seguir manteniendo el mismo comportamiento? ¿Perduran esas \m@switch
definiciones \LMex
más allá del siguiente " }
"?
Si no es así, ¿existe algún otro método para hacer el \ThisStyle
equivalente \SavedStyle
? No se me ocurre nada que funcione en tiempo lineal con respecto a la profundidad de anidamiento y que siga funcionando correctamente en presencia de reentrada.
Respuesta1
Respuesta corta: no, no hay forma de hacer esto correctamente en todas las situaciones o en una sola pasada de LaTeX.
Después de mucho aprendizaje y experimentación, parece que la única forma de solucionar este problema es algo comoRespuesta y comentario de Manuel aquí.. No existe tal cosa como \whatIsTheMathStyleHere
(a menos que estemos en LuaTeX). El\mathchoice
El comando es una primitiva TeX..Se hace la elección de las cuatro opciones.tarde. Para entender lo que significa "tarde", debemos apreciar que TeX tienealgunas etapas digestivas: ojo, boca,garganta, estómago, cada uno de los cuales transforma el documento lógico en una forma más cercana al documento visual final, trabajando a través de un subconjunto de tokens semánticamente significativos.A veces se vuelve a la etapa anterior.(Pero, ¿la inteligencia tipográfica casi demasiado buena para ser verdad que esperamos no justifica cierto grado de complejidad?) Entonces, lo que rodea\mathchoice
yEl interior de sus argumentos se expande macro antes de \mathchoice
aplicarse. De hecho, hasta donde yo sé, no solo la expansión, sino también otros comandos TeX, como \ifx
, se procesan antes \mathchoice
, por lo que dentro de cada etapa de procesamiento podría haber varias subetapas estratificadas.
La alternativa de Manuel, llamada \mathcase
, utiliza un truco inteligente, donde se inserta un espacio a nanoescala, de un tamaño que depende del estilo matemático. Y luego comprueba el tamaño del espacio y determina el estilo. ¿Cómo puede funcionar eso, si se supone que el estilo matemático final en todas partes debe determinarse sólo después de que el documento se convierta en una estructura completamente resuelta? Lo hace utilizando el zref-savepos
paquete. Al leer la documentación de zref
, hay una nota:
La posición de la página no se conoce instantáneamente. Primero, la página debe construirse mediante la rutina de salida asincrónica de TEX. Por lo tanto, el momento en el que se conoce la posición es el tiempo de envío de la página. Por lo tanto, resulta útil un sistema de referencia en el que la información se registra en la primera ejecución y se pone a disposición para su uso en la segunda ejecución.
En otras palabras, el estilo matemático correcto se determina enenviar, momento en el que no se puede utilizar en ninguna \if
u otras estructuras de toma de decisiones, pero se almacena en el archivo AUX (como puede ver al inspeccionar el archivo AUX en el ejemplo siguiente) y queda disponible durante la segunda pasada. .
Desafortunadamente, esto causa el siguiente tipo de problema, con estilos matemáticos en cascada que se propagan a lo largo de una serie anidada de \mathcase
s: si el anidamiento tiene N niveles de profundidad, entonces no se garantiza que el documento sea estable hasta que se compila N veces. Por ejemplo:
(Esto es dela respuesta de manuel, donde acabo de cambiar el cuerpo del documento).
\documentclass{scrartcl}
\usepackage{mathtools}
\usepackage{zref-savepos}
\newcount\mmstynum
\newcount\tmpnum
\protected\def\getmsty
{\global\advance\mmstynum1 %
\expandafter\getstyA\expandafter{\number\mmstynum}}
\protected\def\getstyA#1%
{\zsaveposx{mmsty-#1-a}%
\mathchoice{\kern4sp}{\kern3sp}{\kern2sp}{\kern1sp}%
\zsaveposx{mmsty-#1-b}
\tmpnum=\numexpr
\zposx{mmsty-#1-b} - \zposx{mmsty-#1-a}
\relax
\ifcase\tmpnum\or\kern-1sp \or\kern-2sp \or\kern-3sp \or\kern-4sp \fi}
\protected\def\mstycase
{\ifcase\tmpnum\expandafter\gobblefour\or\expandafter\usefourth\or
\expandafter\usethird\or\expandafter\usesecond\or
\expandafter\usefirst\else\expandafter\gobblefour\fi}
\protected\def\mathcase{\getmsty\mstycase}
\long\def\gobblefour#1#2#3#4{}
\long\def\usefourth#1#2#3#4{#4}
\long\def\usethird#1#2#3#4{#3}
\long\def\usesecond#1#2#3#4{#2}
\long\def\usefirst#1#2#3#4{#1}
\def\tmpa{If this prints it means it doesn't work}
\newcommand*\foo
{\mathcase % compare with \mathchoice
{\def\tmpa{displaystyle}}
{\def\tmpa{textstyle}}
{\def\tmpa{scriptstyle}}
{\def\tmpa{scriptscriptstyle}}
\text\tmpa}
\let\savedstyle\displaystyle
\def\thisstyle#1{\begingroup\mathcase{\let\savedstyle\displaystyle}{\let\savedstyle\textstyle}{\let\savedstyle\scriptstyle}{\let\savedstyle\scriptscriptstyle}#1\endgroup}
\begin{document}
\[
\sum \scriptstyle \sum \thisstyle{%
\fbox{\( \sum \savedstyle \sum \thisstyle{%
\fbox{\( \sum \savedstyle \sum \thisstyle{%
\fbox{\( \sum \savedstyle \sum \)}%
}\)}%
}\)}%
}
\]
\end{document}
Al mirar el PDF en el visor TeXworks mientras lo compilamos, vemos:
Después del primer pase:
Después del segundo pase:
Después del tercer pase:
Después del cuarto pase:
Entonces, la solución compensa el número de pasadas para mejorar la velocidad de cada pasada. (Aunque sería bueno si también le avisara cuando el documento aún no sea estable). Si bien no es una solución perfecta, estoy convencido de que es la mejor alternativa posible, dada la naturaleza de TeX (y TeX es poco probable que cambie en este aspecto en el futuro previsible).
También está elmathstyle
paquete (ver discusión aquí), que funciona alrededor\mathchoice
aprovechando todos los delimitadores del modo matemático (perono\(
aparentemente!), e inyectando algo de lógica para realizar un seguimiento de cuál será el estilo matemático actual, fuera de línea con TeX. Pero, como se señala enEl comentario de Aditya aquí., hay casos en los que no logra predecir el comportamiento de TeX. Por ejemplo, con el uso de \over
primitivas \atop
TeX. (Sin embargo, el comentario tiene 5 años. ¿Quizás haya mejorado mientras tanto?)
Entonces, la mejor respuesta es reducir el número de \mathchoice
niveles de anidamiento (tenga en cuenta que a \mathchoice
está contenido en \ThisStyle
, \text
,\mathpalette
, etc.) cuando sea posible (p. ej.Eliminé algunos redundantes\TextStyle
mensajes redundantes en la pregunta precursora.), o si puedes inferir el estilo matemático usando un razonamiento de sentido común, podríasredefinir\mathchoice
localmente para cortocircuitarlo.
Considerándolo todo, es un resultado sorprendente. Esta es la primera vez que quise hacer algo con LaTeX y resultó poco práctico. Además, mientras intentaba hackear \mathchoice
, me encontré con todos los horrores de los lenguajes macro, donde nunca se sabe qué se expandirá y en qué orden. (Basta con echar un vistazo a la forma "clásica" de ser\expandafter\expandafter\expandafter\expandafter\expandafter...
enesta solución, y sabes que algo anda mal.) Finalmente, para el software de los años setenta, la semántica de \mathchoice
parece algo ineficiente, incluso si su propósito es simplemente componer un único símbolo personalizado...