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

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

在某些情況下,我希望有一種方法來定義命令,\tmp以便

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

我目前的方法只是使用\newcommandor \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}

相關內容