[Tex/LaTex] How to define _or_ redefine a command (mixing \providecommand + \renewcommand)

macros

In some situations I wish there was a way to define a command \tmp so that

  • if \tmp does not exist: Defined \tmp
  • if \tmp does exits: Redefine \tmp

My current approach is simply to use either \newcommand or \renewcommand. However, this means that I often have to change from one version to the other if I reorder my documents and sometimes limits the overall reusability of my code.

In this question I learned about \providecommand, which almost solves my problem: It can be used irrespective of whether \tmp is defined, but it only defines on the first occurrence and does not overwrite. This lead me to the naive attempt:

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

However, this approach is obviously not general enough:

% 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.

Is there any other way to achive the define or overwrite behavior?

Best Answer

Yes, there is a method:

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

Why does it work? Because TeX uses macro expansion and it's irrelevant what \providecommand defines #1 to be, if #1 wasn't defined, because you redefine it immediately.

Now that you know how to do it, try

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

and enjoy the wreck!

There is a reason why LaTeX doesn't provide a \declarecommand function: you MUST be aware whether you are redefining an existent command.

If you want to allow the optional *, then

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

will do.