[Tex/LaTex] Combining newcommand and renewcommand with optional arguments

macros

If I use

\newcommand{\foo}[3][\empty]{#1#2#3}

and want to renew those options by

\newcommand{\renewfoo}[2][\empty]{\renewcommand{\foo}[3][\empty]{???}}

What do I have to note instead of "???", if I want to use #1 and #2 of \renewfoo and still wants to keep #1,#2,#3 of \foo?

Best Answer

(La)TeX allows for nested (re)definition of macros, i.e. (re)definitions inside of other macros. In order to let (La)TeX distinguish between the (possible) arguments of the outer macro and the inner arguments, the number of argument specifiers # etc. has to be doubled for the inner macro, i.e. #1, #2 becomes ##1, ##2 etc.

If there is another level of nesting, the argument specifiers # has to doubled again, i.e.

First level: #1

Second level: ##1

Third level: ####1

Fourth level ########1

etc. (Both more than three levels is weird), with other words: 2^{level-of-nesting-1} occurences of the # character must be used.

I've added a version for xparse as well to get around the 'weird' \empty optional argument parameter. However, I don't suggest the redefinition a) with another wrapper and b) the wrapper having an optional argument as well.

\documentclass{article}

\usepackage{xparse}


\newcommand{\foo}[3][\empty]{%
  #1#2#3%
}

\newcommand{\renewfoo}[2][]{\renewcommand{\foo}[3][#1]{And now for something completely different: #2 and ##2##3[##1]}}

\NewDocumentCommand{\foobar}{o+m+m}{%
  \IfValueT{#1}{#1}%
  #2#3%
}

\NewDocumentCommand{\RenewFooBar}{o+m}{%
  \IfValueTF{#1}{%
    \RenewDocumentCommand{\foobar}{O{#1}+m+m}{%
      And now for something completely different with xparse: #2 and ##2##3[##1]%
    }%
  }{%
    \RenewDocumentCommand{\foobar}{+m+m}{%
      And now for something completely different with xparse: #2 and ##1##2%
    }%
  }%
}

\begin{document}

\foo[A]{B}{C}

\renewfoo{\LaTeXe}

\foo[C]{A}{B}

\foobar{E}{F}

\foobar[D]{E}{F}

\RenewFooBar{Mr. Gumby}

\foobar{E}{F}


\RenewFooBar[Brain Surgeon]{Mr. Gumby}


\foobar{E}{F}



\end{document}