為什麼 amsmath 和 \char 會以這種方式互動?

為什麼 amsmath 和 \char 會以這種方式互動?

我在嘗試重新定義 \char 來表示欄位的特徵時發現了這一點,並收到了一個奇怪的錯誤訊息。下面是一個最小的例子來示範所發生的奇怪的事情。

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

如果您排版此內容,您將獲得編號為1、3 和4 的部分。那時起上,似乎沒有其他東西可以讓它再次被調用。僅當載入 amsmath 套件時才會發生這種情況。世界上到底發生了什麼事?有什麼方法可以讓我重新定義 \char 而不引起奇怪的問題嗎?

答案1

太長了;博士

是否可以安全地重新定義\char?不是沒有很多的工作將被證明是無用的。

切勿執行\renewcommand您不了解的命令。對於你的命令做

\DeclareMathOperator{\Char}{char}

並使用\Char.或者可能\fldchar,選擇你認為最好的名字,但是不是 \char

擴展答案

具體錯誤是由於在其宏中amsmath使用了該宏,每次在字體大小更改後首次出現數學公式時都會執行該宏。\char\resetMathstrut@

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

除了告訴它設定了一個在對齊環境中使用的數學支柱之外,實際上沒有必要描述這個巨集的作用。

在您的程式碼中,該巨集僅執行一次,但如果您在參數中新增公式,\section您將看到它再次執行。

有沒有辦法安全地重新定義\char?是的,有:製作整個 LaTeX 樹的自己的副本,添加到\let\primitivechar\char(的副本) 的開頭latex.ltx;然後將\char整棵樹中所有其他出現的 替換為\primitivechar。然後重新編譯格式。你永遠不知道哪個包可能會使用\char.

運行ack(或grep) 表示\char在總共 960 個檔案中出現了 8682 次:

> 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

但請考慮一下,除了您之外,沒有人能夠在您的文件上運行 LaTeX。所以你的問題的答案是

是的,但出於所有實際目的,不是。

一些背景。 LaTeX3 的最初目標之一是取消定義每個原語,用別名替換它們。然而,團隊意識到這是不切實際的,因為這意味著基本上沒有當前的軟體包可以與新版本一起使用,而且有數千個軟體包!

為什麼原來的LaTeX沒有做這一步呢?由於各種原因,主要有以下幾點:

  1. 在編寫 LaTeX 時,plain TeX 是唯一可用的格式,而 LaTeX 借用了幾種 plain 結構;

  2. 從 plain 到 LaTeX 的轉換會更容易,允許重複使用程式碼;

  3. 電腦記憶體匱乏;真的稀缺。

當 LaTeX2e 發佈時,可能是進行對每個原語進行別名並用別名替換它們的項目的機會,因為包並不那麼多。但 LaTeX 基本上不能在任何機器上運行,因為每個別名都佔用記憶體空間。如今,這種記憶體考慮不再是問題,但包數量已達數千個。

在某些情況下,可以重新定義基元,但只是為了稍微改變其行為:\input例如,LaTeX 使用 來實現,但重新定義的\input最終總是會呼叫基元的別名。

答案2

\char是按數字存取字元的 TeX 原語,因此重新定義它將破壞各種乳膠結構,而不僅僅是amsmath

\documentclass{article}

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


\begin{document}

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

LaTeX 無法選擇正確大小的圓。

始終使用\newcommand以避免意外的重新定義。僅\renewcommand當您希望更改現有命令的所有使用的行為時才使用。

相關內容