Como redefinir `\ mathrel` sem quebrar` \ overset`?

Oct 09 2020

Parece que não posso modificar \mathrelsem quebrar \overset, e não entendo por quê. O seguinte falha ao compilar, mesmo quando a redefinição de \mathrelfaz exatamente o mesmo que a versão original.

\documentclass{article}
\usepackage{amsmath}
\usepackage[T1]{fontenc}
\begin{document}
\let\oldmathrel\mathrel
\def\mathrel#1{\oldmathrel{#1}}
$A \overset{X}{\to} B$
\end{document}

A mensagem de erro é:

Runaway argument?
\relax\@nil \binrel@@ {\mathop {\kern \z@ \to }\limits ^{X}} B$ \end \ETC.
! File ended while scanning use of \@tempb.
<inserted text> 
                \par 

O que está acontecendo?

Respostas

3 UlrikeFischer Oct 09 2020 at 06:49

\mathrelé um comando primitivo tex usado em todo o lugar. Você não deve alterá-lo sem realmente entender como funcionam esses primitivos e sem a habilidade de rastrear o código.

Em seu exemplo, ele falha porque o primitivo não aceita um argumento. Isso significa que você pode fazer algo assim:

\documentclass{article}

\begin{document}

$abc$

$a\ifnum 1=1 \mathrel \else \mathbin \fi b c$

\end{document}

Se você adicionar sua redefinição, de \mathrelrepente pegará o \elseargumento as e, em seguida, o código se desfaz:

\mathrel #1->\oldmathrel {#1}
#1<-\else 

! Missing } inserted.
<inserted text> 
                }
l.24 $a\ifnum 1=1 \mathrel \else \mathbin \fi b c$

Algo semelhante acontece com o overset, pois as definições de amsmath \mathreltambém usam dentro de um \if-teste:

    \ifdim\wdz@<\z@ \mathbin
    \else\ifdim\wdz@>\z@ \mathrel
    \else \relax\fi\fi
user21820 Oct 10 2020 at 17:00

Não sei por que a resposta de egreg foi excluída, porque havia um comentário útil embaixo dela (não me lembro por quem) que deu uma solução muito simples:

\protected\def\mathrel#1{\oldmathrel{#1}}

Eles alertaram que isso pode quebrar outros pacotes, mas usar isso não causa problemas para mim, então funciona para mim.