如果命令不存在,为什么 \renewcommand 会出错?

如果命令不存在,为什么 \renewcommand 会出错?

我在几个项目中使用相同的前言。已定义的命令集在不同的环境中有所不同。在一个项目中,\eps已定义,而在另一个项目中则未定义。我希望定义\eps\varepsilon

Latex2e 非官方参考手册说:

如果您尝试定义一个命令,而该名称已被使用,那么您将得到类似 的结果<error>。如果您尝试重新定义一个命令,而该名称尚未被使用,那么您将得到类似 的结果<different error>

因此,在我的情况中,两者都不能使用。我可以像这样解决这个问题:

\ifdefined\eps
    \renewcommand{\eps}{\varepsilon}
\else
    \newcommand{\eps}{\varepsilon}
\fi

但这很笨拙。我不明白\renewcommand如果命令不存在,为什么要抱怨。无论如何,我们都在提供我们想要的命令定义。

答案1

“为什么”的问题很难回答。在这种情况下,答案是“因为 Leslie Lamport 在 20 世纪 80 年代初选择了这个定义”。

但是如果\renewcommand按照你的建议去做,那么它就相当于\newcommand根本不检查所定义的命令。这将否定\newcommand这样做的大部分原因,即保护用户免于意外重新定义 latex 内部结构并破坏系统。

正如 Steven 在您的问题下评论的那样,这种行为就像 TeX 原语一样\def,它总是定义(或重新定义)提供的命令。即使现在,您也经常看到用户\def在 latex 文档中使用并覆盖内部命令。

这个想法是,\newcommand如果某些事情即将出错,你就会使用它并得到警告,然后只有当你知道可以这样做时,才使用它\renewcommand进行重新定义。

您可以更简单地定义您的命令

  \def\zzcommand#1{\let#1\undefined\newcommand#1}

它首先取消命令的定义,以便\newcommand始终成功,然后尝试

\zzcommand\box{\fbox{X}}

例如。

答案2

如果其中一个环境\eps已经定义为给出 epsilon 的形式之一,则只需执行

\providecommand{\eps}{\varepsilon}
\renewcommand{\epsilon}{\varepsilon}

并且将在两种环境中\eps产生使用。\varepsilon

如果\eps定义为做其他事情,那么你就完了。


为什么\renewcommand如果输入了未定义的命令,就会犹豫不决?因为\renewcommand应该小心使用,并且知道自己在做什么。

答案3

这是 Leo Liu 的回答中的一个简单例子这里

\providecommand\foo仅当此命令先前未定义时才重新定义该命令。

如果\newcommand定义了\foo,那么\providecommand将会保持沉默。

有了\providecommand,就永远存在一个\foo成为meh\renewcommand

我不确定这是否是最优雅的答案,但它非常简单明了。

\documentclass{article}
% (un)comment to change \providecommand behavior
\newcommand{\foo}{foo}
% if {\foo} not defined, then {\foo} is ``bla''
\providecommand{\foo}{bla}
% {\foo} will always become ``meh''
\renewcommand{\foo}{meh}
\begin{document}
{\foo}
\end{document}

相关内容