33

I'm trying to renew a command in terms of its old definition... something similar to this:

\renewcommand{\vec}[1]{\vec{\mathbf{#1}}}

But this seems to send the interpreter in an infinite loop. How do I do this properly?

0

2 Answers 2

29

You can use the \let command to help you as follows

\let\oldvec\vec
\renewcommand{\vec}[1]{\oldvec{\mathbf{#1}}}

Here's a complete MWE

% arara: pdflatex
\documentclass{article}
\let\oldvec\vec
\renewcommand{\vec}[1]{\oldvec{\mathbf{#1}}}

\begin{document}

$\vec{x}+\vec{y}$

\end{document}
5
  • +1 Hmm, it seems like this "pollutes" the following code with the definition of oldvec. Is there any way to avoid that (and also not rely on oldvec being undefined in the beginning)?
    – user541686
    Mar 9, 2013 at 19:46
  • @Mehrdad, the pollution of oldvec should not be noticeable. And often one might be forced to use the other definition (take for example \varphi and \phi which I often change the order of by \let\ophi\phi\let\ovarphi\varphi\let\phi\ovarphi\let\varphi\ophi, etc. It doesn't really matter in terms of efficiency, if thats what you are worried about?
    – nickpapior
    Mar 9, 2013 at 20:28
  • Nah it's not efficiency, it's just that, being a programmer, it feels like bad practice to me, so if there's a way to make it foolproof I'd rather do that. :)
    – user541686
    Mar 9, 2013 at 20:30
  • 1
    @Mehrdad: cmhughes' uses the idiomatic technique here. From the point of view of debugging, it is easier to see what is happening if one macro is defined in terms of another than to partially expand out the old macro (which should be possible using \expandafter). Mar 9, 2013 at 21:31
  • @CharlesStewart: I see, thanks for explaining that.
    – user541686
    Mar 10, 2013 at 4:04
10

You can avoid defining an "intermediate" command in some cases; consider the following code:

\documentclass{article}
\newcommand{\foo}[1]{\mbox{#1}}
\show\foo

\begingroup\def\temp{\renewcommand\foo[1]}
\expandafter\expandafter\expandafter\endgroup
\expandafter\temp\expandafter{\foo{\textbf{#1}}}
\show\foo
\show\temp

The log file will show

> \foo=\long macro:
#1->\mbox {#1}.
l.3 \show\foo

? 
> \foo=\long macro:
#1->\mbox {\textbf {#1}}.
l.8 \show\foo

? 
> \temp=undefined.
l.9 \show\temp

so you can see that \foo has been redefined as the original \foo, but with the argument printed boldface, whereas \temp is still undefined. So we actually use an intermediate command, but its definition is forgotten as soon as the redefinition is performed.

This works with \vec; however \vec is not a macro with argument, as \show\vec will show:

> \vec=macro:
->\mathaccent "017E\relax .

where \mathaccent is a TeX primitive. Yes, this works:

\begingroup\def\temp{\renewcommand\vec[1]}
\expandafter\expandafter\expandafter\endgroup
\expandafter\temp\expandafter{\vec{\textbf{#1}}}

I leave to your judgement as a programmer if this is clearer than

\let\LaTeXvec\vec
\renewcommand\vec[1]{\LaTeXvec{\mathbf{#1}}}

TeX is different from other programming languages, because it works mainly by macro expansion and a macro can have just one definition at a given time.

However, one has to take much care not only to check whether \LaTeXvec is defined (using a complicated prefix rather than old is usually safe). There are big problems if the command we want to save is not defined simply with \newcommand (or \def). See When to use \LetLtxMacro? for some of them. In those cases the \expandafter path shown above will definitely not work.

1
  • @Qrrbrbirlbel In the first case, every attempt of that kind will fail miserably. This way works in various cases, but certainly is much more difficult if something has to be put before the original command. Thus the \let or, better, \LetLtxMacro road is surely preferable.
    – egreg
    Mar 9, 2013 at 22:01

Not the answer you're looking for? Browse other questions tagged .