¿Por qué amsmath y \char interactúan de esta manera?

¿Por qué amsmath y \char interactúan de esta manera?

Descubrí esto al intentar redefinir \char para indicar la característica de un campo y recibí un mensaje de error extraño. A continuación se muestra un ejemplo mínimo para demostrar lo extraño que sucedió.

\documentclass[12pt]{article}

\usepackage{amsmath}

\renewcommand{\char}{\stepcounter{section}}

\begin{document}

\section{test}

test$1 + 1 = 2$test$2 + 2 = 4$test

\section{test}

test$1 + 1 = 2$test$2 + 2 = 4$test

\section{test}

\end{document}

Si escribe esto, obtendrá las secciones numeradas 1, 3 y 4. Al experimentar con esto, he determinado que el primer entorno matemático en línea, matemático en pantalla o alineación de un documento hace que se llame a \char una vez, y desde entonces adelante, nada más parece ser capaz de hacer que se vuelva a llamar. Esto SÓLO sucede si se carga el paquete amsmath. ¿Qué sucede? ¿Hay alguna manera de redefinir \char sin causar problemas extraños?

Respuesta1

tl; dr

¿Es posible redefinir de forma segura \char? No sinmuchode trabajo que resultaría inútil.

Nunca hagas \renewcommanduna orden que no conoces. Por tu comando hazlo

\DeclareMathOperator{\Char}{char}

y use \Char. O tal vez \fldchar, elige el nombre que creas mejor, perono \char.

respuesta extendida

El error específico se debe al hecho de que amsmathutiliza \charen su \resetMathstrut@macro, que se ejecuta cada vez que aparece por primera vez una fórmula matemática después de un cambio de tamaño de fuente.

\def\resetMathstrut@{%
  \begingroup
  \setbox\z@\hbox{%
    \mathchardef\@tempa\mathcode`\(\relax
    \def\@tempb##1"##2##3{\the\textfont"##3\char"}%
    \expandafter\@tempb\meaning\@tempa \relax
  }%
 \edef\@tempa{%
     \ht\Mathstrutbox@\the\ht\z@\relax
     \dp\Mathstrutbox@\the\dp\z@\relax}%
  \expandafter\endgroup\@tempa
}

Realmente no es necesario describir lo que hace esta macro, aparte de decir que configura un puntal matemático para ser utilizado en los entornos de alineación.

Con tu código, esta macro se ejecuta solo una vez, pero si agregas una fórmula en el argumento \sectionverás que se ejecuta una vez más.

¿Hay alguna manera de redefinir de forma segura \char? Sí, lo hay: haga su propia copia de todo el árbol LaTeX, agréguelo \let\primitivechar\charal principio de (la copia de) latex.ltx; luego reemplace todas las demás apariciones de \charen todo el árbol con \primitivechar. Luego vuelva a compilar los formatos. Nunca se sabe qué paquete podría utilizar \char.

Una ejecución de ack(o grep) indica que \charaparece 8682 veces en un total de 960 archivos:

> ack -ch '\\char[^a-z]' /usr/local/texlive/2022/texmf-dist/tex/latex/
8682
> ack -cl '\\char' /usr/local/texlive/2022/texmf-dist/tex/latex/ | wc -l
960

Sin embargo, considere que nadie más que usted podrá ejecutar LaTeX en su documento. Entonces la respuesta a tu pregunta es

Sí, pero a todos los efectos prácticos, no.

Algunos antecedentes. Uno de los objetivos originales de LaTeX3 eraindefinircada primitivo, reemplazándolos con alias. Sin embargo, el equipo se dio cuenta de que esto no es práctico, porque significaría que esencialmente ningún paquete actual podría usarse con la nueva versión y ¡hay miles de ellos!

¿Por qué el LaTeX original no hizo este paso? Por diversos motivos, aquí te dejamos los principales:

  1. en el momento en que se escribió LaTeX, TeX simple era el único formato disponible y LaTeX tomó prestadas varias construcciones simples;

  2. la transición de simple a LaTeX sería más fácil, permitiendo reutilizar el código;

  3. la memoria de la computadora era escasa;en realidadescaso.

Cuando se lanzó LaTeX2e, podría haber sido una ocasión para continuar con el proyecto de asignar un alias a cada primitivo y reemplazarlos con alias, porque los paquetes no eran tantos. Pero LaTeX no se ejecutaría básicamente en ninguna máquina, porque cada alias ocupa espacio en la memoria. Hoy en día, estas consideraciones sobre la memoria no son un problema, pero los paquetes se cuentan por miles.

En algunos casos es posible redefinir una primitiva, pero sólo para cambiar un poco su comportamiento: LaTeX lo hace con \input, por ejemplo, pero la redefinida \inputsiempre eventualmente llamará el alias de la primitiva.

Respuesta2

\chares la primitiva TeX para acceder a un carácter por número, por lo que redefinirla romperá todo tipo de construcciones de látex, no soloamsmath

\documentclass{article}

\renewcommand{\char}{\stepcounter{section}}


\begin{document}

\begin{picture}(0,0)
\put(0,0){\circle{5}}
\end{picture}
\end{document}

LaTeX no puede seleccionar un círculo del tamaño correcto.

Úselo siempre \newcommandpara evitar redefiniciones accidentales. Utilícelo únicamente \renewcommandcuando desee cambiar el comportamiento de todos los usos de un comando existente.

información relacionada