如何定义或重新定义命令(混合 \providecommand + \renewcommand)?

如何定义或重新定义命令(混合 \providecommand + \renewcommand)?

在某些情况下,我希望有一种方法可以定义一个命令,\tmp以便

  • 如果\tmp不存在:定义\tmp
  • 如果\tmp退出:重新定义\tmp

我目前的方法只是使用 或\newcommand\renewcommand但是,这意味着如果我重新排序文档,我经常必须从一个版本更改为另一个版本,有时会限制代码的整体可重用性。

这个问题我了解了\providecommand,这几乎解决了我的问题:无论是否\tmp定义,它都可以使用,但它只会在第一次出现时定义并且不会覆盖。这让我做了一个天真的尝试:

\newcommand{\overwritecommand}[2]{
  \providecommand{#1}{#2}
  \renewcommand{#1}{#2}
}

但是,这种方法显然不够通用:

% it works for
\overwritecommand{\tmp}{test}

% but not for commands with arguments like
\overwritecommand{\tmp}[1]{test: #1} 
% Error: You can't use `macro parameter character #' in horizontal mode.

还有其他方法可以实现定义或覆盖行为?

答案1

是的,有一个方法:

\newcommand{\declarecommand}[1]{\providecommand{#1}{}\renewcommand{#1}}

它为什么有效?因为 TeX 使用宏扩展,并且\providecommand定义什么并不重要#1,如果#1没有定义,因为您会立即重新定义它。

现在你知道该怎么做了,试试吧

\declarecommand{\box}[1]{\fbox{#1}}

并欣赏沉船的景象!

那里LaTeX 不提供函数的原因\declarecommand:你必须请注意您是否正在重新定义现有的命令。

如果你想允许可选的*,那么

\makeatletter
\newcommand\declarecommand{\@star@or@long\@declarecommand}
\newcommand\@declarecommand[1]{%
  \provide@command{#1}{}%
  \renew@command{#1}%
}
\makeatother

会做。

答案2

我理解你需要,\def但使用像这样的参数\newcommand。我们可以定义自己的\newcommand,忽略定义的控制序列是否有意义。例如,我们可以使用来自的代码这一页

\def\newcommand#1{\isnextchar[{\newcommandA#1}{\newcommandA#1[0]}}
\def\newcommandA#1[#2]{\edef\tmpp{\ifcase#2%
   \or1\or12\or123\or1234\or12345\or123456\or1234567\or12345678\or123456789\fi}%
   \edef\tmpp{\expandafter\addhashs\tmpp.}%
   \isnextchar[{\newcommandB#1}{\long\expandafter\def\expandafter#1\tmpp}%
}
\def\newcommandB#1[#2]{%
   \def#1{\isnextchar[{\runcommand#1}{\runcommand#1[#2]}}%
   \long\expandafter\def\csname\string#1X\expandafter\endcsname\tmpp
}
\def\addhashs#1{\ifx.#1\else #####1\expandafter\addhashs\fi}
\long\def\runcommand#1[#2]{\csname\string#1X\endcsname{#2}} 

答案3

因为经典的例子已经展示了,我只需添加一种xparse非常用户友好的方法:

\documentclass{article}
\usepackage{xparse}
\DeclareDocumentCommand{\foo}{m}
 {Foo: #1}
\begin{document}

\foo{bar}

\DeclareDocumentCommand{\foo}{om}
 {\IfNoValueTF{#1}%
   {Bar: no optional, just #2}%
   {Bar: optional = #1, plus #2}%
 }%

\foo{Baz}

\foo[Bar]{Baz}

\end{document}

相关内容