我在嘗試重新定義 \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沒有做這一步呢?由於各種原因,主要有以下幾點:
在編寫 LaTeX 時,plain TeX 是唯一可用的格式,而 LaTeX 借用了幾種 plain 結構;
從 plain 到 LaTeX 的轉換會更容易,允許重複使用程式碼;
電腦記憶體匱乏;真的稀缺。
當 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
當您希望更改現有命令的所有使用的行為時才使用。