私は、フィールドの特性を示すために \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 の番号が付けられたセクションが表示されます。これを試してみたところ、ドキュメントの最初のインライン数式、表示数式、または配置環境で \char が 1 回呼び出され、それ以降は他の方法では再度呼び出すことができないことがわかりました。これは、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
}
このマクロが何を行うかについては、アライメント環境で使用される数学ストラットを設定すること以外、実際に説明する必要はありません。
あなたのコードでは、このマクロは 1 回だけ実行されますが、引数に数式を追加すると、\section
もう一度実行されることがわかります。
を安全に再定義する方法はありますか\char
? はい、あります。LaTeX ツリー全体のコピーを作成し、\let\primitivechar\char
の先頭 (のコピー) に追加します。次に、ツリー全体で が 1 つおきに出現する部分を に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 が書かれた当時は、プレーン TeX が唯一の利用可能な形式であり、LaTeX はいくつかのプレーンな構造を借用していました。
プレーンから 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
既存のコマンドのすべての使用の動作を変更する場合にのみ使用してください。