如何正确地重新定义命令以避免递归调用自身?

如何正确地重新定义命令以避免递归调用自身?

我正在尝试根据旧的定义来更新命令……类似于此:

\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上面显示的路径肯定不起作用。

相关内容