\(re)newcommand 不关心命令是否已定义

\(re)newcommand 不关心命令是否已定义

是否存在 的版本\newcommand,类似于无论是否之前已定义\extranewcommand{\foo}{bar},都定义 代表什么\foo?当然,如果未定义,则可以使用,如果 已定义,则可以使用。但是,无论哪种情况,都必须知道使用哪个版本:如果选择错误,文档将无法编译。我感兴趣的是是否存在类似的命令(或者可能是命令组合等),可以在任何一种情况下工作。bar\foo\foo\newcommand{\foo}{bar}\renewcommand{\foo}{bar}

为了合理化这个问题,下面是两种我认为该命令有用的情况。当然,变化很小,但我认为随着时间的推移它会逐渐增加。

  1. 人们并不总是知道哪些命令已经定义。有时,新定义的命令恰好也是某些标准包中定义的命令。例如,人们想使用\operatorname{Im}表示线性算子的图像,因此声明 很方便\newcommand{\Im}{\operatorname{Im}}。但是,\Im已经是虚部的奇特符号,因此renewcommand需要 。我从未使用过提到的虚部符号,所以如果我可以忘记它的存在就好了(但我不能)。(当然,可以通过编译、注意错误并在“newcommand”前面添加“re”来解决此问题;但是,还有很多其他类似的冲突发生。)
  2. 我使用了很多只“本地”使用的命令(我不确定这是否是一种好的编码习惯,但我发现它很有用)。例如,如果我有一个集合 S,它出现在文本的许多地方,我经常会声明\newcommand{\Set}{S}或甚至\newcommand{\S}{S},这样我就可以很容易地将符号 S 更改为另一个,如果我愿意的话。这可能会导致命令频繁更新,这不是什么大问题。但是,如果带有的文本块移动\newcommand,那么前缀也re必须移动。(同样,这不是什么大问题,但我觉得很麻烦)。

答案1

\providecommand如果尚未定义,则定义一个宏。同时\renewcommand您还有“ \extranewcommand”:

\providecommand{\foo}{}
\renewcommand{\foo}[1]{bar: #1}

或者您可以切换到普通的 TeX 原语(其他语法!),例如:

\long\def\foo#1{bar: #1}

\renewcommand和没有使用星号的朋友一样\long\def,如果给出了星号形式,则使用\def没有\long。此外,参数的指定也不同。)

\declarecommand

\declarecommand调用\providecommand和一起的“请求”的定义\renewcommand

\documentclass{article}

\makeatletter
\newcommand*{\declarecommand}{%
  \@star@or@long\declare@command
}
\newcommand*{\declare@command}[1]{%
  \provide@command{#1}{}%
  % \let#1\@empty % would be more efficient, but without error checking
  \renew@command{#1}%
}
\makeatother

\begin{document}

\declarecommand*{\foo}{\typeout{foo 1: \meaning\foo}}
\foo
\declarecommand{\foo}{\typeout{foo 2: \meaning\foo}}
\foo
\declarecommand*{\foo}[1]{\typeout{foo #1: \meaning\foo}}
\foo{3}

\end{document}

结果:

foo 1: macro:->\typeout {foo 1: \meaning \foo }
foo 2: \long macro:->\typeout {foo 2: \meaning \foo }
foo 3: macro:#1->\typeout {foo #1: \meaning \foo }

答案2

它不像Heiko 的回答但另一种选择是

\ifdefined\foo
\renewcommand{\foo}[1]{bar: #1}
\else
\newcommand{\foo}[1]{bar: #1}
\fi

请注意,这\ifdefinede-TeX 扩展并且是任何现代 LaTeX 编译器的一部分。无需任何软件包。

答案3

你可以放

\newcommand{\foo}[1]{to be renewed}

在你的序言中,然后

\renewcommmand{\foo}[1]{whatever #1}

无论你喜欢什么。

如果\foo恰好在您开始时就已定义,您会发现这一点并可以选择另一个名称,或者在序言中进行更新。

答案4

这是一个很老的线程,但是人们在谷歌时会发现它,所以我将提供我的解决方案:

(确保\usepackage{suffix}在序言中有)

\long\def \forcecommand #1{\providecommand{#1}{}\renewcommand{#1}}

\WithSuffix\def \forcecommand*#1{\providecommand*{#1}{}\renewcommand*{#1}}

\forcecommand本质上只“抓取”传递给它的第一个参数,将其应用于\providecommand\renewcommand,然后将其余部分留给\renewcommand

相关内容