![如何正确地重新定义命令以避免递归调用自身?](https://linux22.com/image/264272/%E5%A6%82%E4%BD%95%E6%AD%A3%E7%A1%AE%E5%9C%B0%E9%87%8D%E6%96%B0%E5%AE%9A%E4%B9%89%E5%91%BD%E4%BB%A4%E4%BB%A5%E9%81%BF%E5%85%8D%E9%80%92%E5%BD%92%E8%B0%83%E7%94%A8%E8%87%AA%E8%BA%AB%EF%BC%9F.png)
我正在尝试根据旧的定义来更新命令……类似于此:
\renewcommand{\vec}[1]{\vec{\mathbf{#1}}}
但这似乎使解释器陷入无限循环。我该如何正确地做到这一点?
答案1
您可以使用\let
以下命令来帮助您
\let\oldvec\vec
\renewcommand{\vec}[1]{\oldvec{\mathbf{#1}}}
以下是完整的 MWE
% arara: pdflatex
\documentclass{article}
\let\oldvec\vec
\renewcommand{\vec}[1]{\oldvec{\mathbf{#1}}}
\begin{document}
$\vec{x}+\vec{y}$
\end{document}
答案2
在某些情况下,您可以避免定义“中间”命令;考虑以下代码:
\documentclass{article}
\newcommand{\foo}[1]{\mbox{#1}}
\show\foo
\begingroup\def\temp{\renewcommand\foo[1]}
\expandafter\expandafter\expandafter\endgroup
\expandafter\temp\expandafter{\foo{\textbf{#1}}}
\show\foo
\show\temp
日志文件将显示
> \foo=\long macro:
#1->\mbox {#1}.
l.3 \show\foo
?
> \foo=\long macro:
#1->\mbox {\textbf {#1}}.
l.8 \show\foo
?
> \temp=undefined.
l.9 \show\temp
因此您可以看到 已\foo
被重新定义为原始的\foo
,但参数以粗体显示,而\temp
仍未定义。因此我们实际上使用了一个中间命令,但一旦执行重新定义,它的定义就会被遗忘。
这与 ; 一起工作,\vec
但是\vec
不是带有参数的宏,如下\show\vec
所示:
> \vec=macro:
->\mathaccent "017E\relax .
其中\mathaccent
是 TeX 基元。是的,这有效:
\begingroup\def\temp{\renewcommand\vec[1]}
\expandafter\expandafter\expandafter\endgroup
\expandafter\temp\expandafter{\vec{\textbf{#1}}}
我留给你作为程序员的判断,看看这是否比
\let\LaTeXvec\vec
\renewcommand\vec[1]{\LaTeXvec{\mathbf{#1}}}
TeX 与其他编程语言不同,因为它的工作原理主要是宏扩展并且宏在给定时间只能有一个定义。
然而,我们必须采取很多不要只关心检查是否\LaTeXvec
已定义(使用复杂的前缀而不是old
通常是安全的)。大的如果我们想要保存的命令不是简单地用\newcommand
(或\def
)来定义的,则会出现问题。请参见何时使用 \LetLtxMacro?对于其中一些情况。在这些情况下,\expandafter
上面显示的路径肯定不起作用。