Por que amsmath e \char interagem dessa maneira?

Por que amsmath e \char interagem dessa maneira?

Descobri isso ao tentar redefinir \char para denotar a característica de um campo e recebi uma mensagem de erro estranha. Abaixo está um exemplo mínimo para demonstrar a coisa estranha que aconteceu.

\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}

Se você digitar isso, obterá seções numeradas 1, 3 e 4. Experimentando isso, determinei que a primeira matemática embutida, matemática de exibição ou ambiente de alinhamento de um documento faz com que \char seja chamado uma vez e, a partir de então, ligado, nada mais parece ser capaz de fazê-lo ser chamado novamente. Isso SOMENTE acontece se o pacote amsmath estiver carregado. O que anda acontecendo no mundo? Existe alguma maneira de redefinir \char sem causar problemas estranhos?

Responder1

dr.

É possível redefinir com segurança \char? Não sembastantede trabalho que se revelaria inútil.

Nunca execute \renewcommandum comando que você não conhece. Para o seu comando faça

\DeclareMathOperator{\Char}{char}

E use \Char. Ou talvez \fldchar, escolha o nome que achar melhor, masnão \char.

Resposta estendida

O erro específico se deve ao fato de amsmathutilizar \charem sua \resetMathstrut@macro, que é executada toda vez que uma fórmula matemática aparece pela primeira vez após uma alteração no tamanho da fonte.

\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
}

Não é realmente necessário descrever o que esta macro faz, além de dizer que ela configura um suporte matemático para ser usado nos ambientes de alinhamento.

Com o seu código, esta macro é executada apenas uma vez, mas se você adicionar uma fórmula no argumento, \sectionverá que ela será executada mais uma vez.

Existe uma maneira de redefinir com segurança \char? Sim, existe: faça sua própria cópia de toda a árvore LaTeX, adicione \let\primitivechar\charno início de (a cópia de) latex.ltx; em seguida, substitua todas as outras ocorrências de \charem toda a árvore por \primitivechar. Em seguida, recompile os formatos. Você nunca sabe qual pacote pode usar \char.

Uma execução de ack(ou grep) informa que \charaparece 8.682 vezes em um total de 960 arquivos:

> 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

Considere, porém, que ninguém além de você seria capaz de executar o LaTeX no seu documento. Então a resposta para sua pergunta é

Sim, mas para todos os efeitos práticos, não.

Alguns antecedentes. Um dos objetivos originais do LaTeX3 eraindefinircada primitivo, substituindo-os por aliases. Contudo, a equipe percebeu que isso é impraticável, porque significaria que essencialmente nenhum pacote atual poderia ser usado com a nova versão e existem milhares deles!

Por que o LaTeX original não executou esta etapa? Por vários motivos, aqui estão os principais:

  1. na época em que o LaTeX foi escrito, o TeX simples era o único formato disponível e o LaTeX emprestou várias construções simples;

  2. a transição do simples para o LaTeX seria mais fácil, permitindo a reutilização do código;

  3. a memória do computador era escassa;realmenteescasso.

Quando o LaTeX2e foi lançado, pode ter sido uma ocasião para continuar o projeto de criar alias para cada primitivo e substituí-los por alias, porque os pacotes não eram tantos. Mas o LaTeX não funcionaria basicamente em nenhuma máquina, porque cada alias ocupa espaço de memória. Hoje em dia, essas considerações de memória não são um problema, mas os pacotes contam aos milhares.

Em alguns casos é possível redefinir uma primitiva, mas apenas para mudar um pouco seu comportamento: o LaTeX faz isso com \input, por exemplo, mas o redefinido \inputsempre eventualmente chamará o alias da primitiva.

Responder2

\charé a primitiva TeX para acessar um caractere por número, redefinindo isso quebrará todos os tipos de construções de látex, não apenasamsmath

\documentclass{article}

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


\begin{document}

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

O LaTeX não consegue selecionar um círculo do tamanho certo.

Utilize sempre \newcommandpara evitar redefinições acidentais. Use apenas \renewcommandquando desejar alterar o comportamento de todos os usos de um comando existente.

informação relacionada