I'm very puzzled by the effect of a \renewcommand with two macros as arguments that appears to affect the value of a third macro. This all occurs within a command to which all three macros are passed as arguments. Here's an MWE; I've printed intermediate values of relevant variables to isolate where the "problem" is occurring:

\documentclass{article}
\usepackage{color}
\newcommand{\mA}{3.1}
\newcommand{\mB}{0}
\newcommand{\mC}{8.2}
\newcommand{\saveSwapValue}[3]{%
\noindent
Before executing either \texttt{\textbackslash{}renewcommand}:\\
\#1: #1\\
\#2: #2\\
\#3: #3\\
    \renewcommand{#2}{#1}
After \texttt{\textbackslash{}renewcommand\{\#2\}\{\#1\}}  \\
\#1: #1\\
\#2: #2\\
\#3: #3\\
    \renewcommand{#1}{#3}
After \texttt{\textbackslash{}renewcommand\{\#1\}\{\#3\}}  \\
\#1: #1\\
\textcolor{red}{\#2: #2}\\
\#3: #3\\
}
\begin{document}
\saveSwapValue{\mA}{\mB}{\mC}
\texttt{\textbackslash{}mB}: \mB.\\
\end{document}

Here's the output:

enter image description here

The unexpected result is highlighted in red: The value of the second argument, \mB, was changed by \renewcommand{\mA}{\mC}. I would have expected instead that \mB would have been unaffected by this second \renewcommand.

I'd sure appreciate being enlightened about what I'm not understanding!

  • Most likely: use \let #2 = #1 instead of \renewcommand{#2}{#1}, and so on for the others. – Bruno Le Floch Aug 17 at 23:25
up vote 10 down vote accepted

Remember that with \renewcommand{<cmd>}{<stuff>}, any subsequent use of <cmd> is replaced with <stuff>. Viewed differently, using a more practical example,

\renewcommand{\mB}{\mA}

just replaces \mB with \mA - not whatever is stored in \mA - with every call to \mB. That's because (La)TeX doesn't expand the value of \mA at the time of (re)definition of \mB when using \renewcommand.

So, after \renewcommand{\mB}{\mA} (-> below should be interpreted as expansion),

\mA -> 3.1
\mB -> \mA -> 3.1

Then, after \renewcommand{\mA}{\mC},

\mA -> \mC -> 8.2
\mB -> \mA -> \mC -> 8.2
\mC -> 8.2

If you wanted to copy the value of \mA into \mB (in an expanded fashion), then you can try \edef or \let instead:

enter image description here

\documentclass{article}

\usepackage{xcolor}

\newcommand{\saveSwapValueA}[3]{%
  \noindent
  Before executing either \texttt{\string\renewcommand}: \\
  \#1: \texttt{\string#1}: #1 \\
  \#2: \texttt{\string#2}: #2 \\
  \#3: \texttt{\string#3}: #3 \\
      \renewcommand{#2}{#1}
  After \texttt{\string\renewcommand\string{\string#2\string}\string{\string#1\string}}: \\
  \#1: \texttt{\string#1}: #1 \\
  \#2: \texttt{\string#2}: #2 \\
  \#3: \texttt{\string#3}: #3 \\
      \renewcommand{#1}{#3}
  After \texttt{\string\renewcommand\string{\string#1\string}\string{\string#3\string}}: \\
  \#1: \texttt{\string#1}: #1 \\
  \textcolor{red}{\#2: \texttt{\string#2}: #2} \\
  \#3: \texttt{\string#3}: #3 \\
}

\newcommand{\saveSwapValueB}[3]{%
  \noindent
  Before executing either \texttt{\string\let}: \\
  \#1: \texttt{\string#1}: #1 \\
  \#2: \texttt{\string#2}: #2 \\
  \#3: \texttt{\string#3}: #3 \\
      \let#2=#1
  After \texttt{\string\let\string#2=\string#1}: \\
  \#1: \texttt{\string#1}: #1 \\
  \#2: \texttt{\string#2}: #2 \\
  \#3: \texttt{\string#3}: #3 \\
      \let#1=#3
  After \texttt{\string\let\string#1=\string#3}: \\
  \#1: \texttt{\string#1}: #1 \\
  \textcolor{red}{\#2: \texttt{\string#2}: #2} \\
  \#3: \texttt{\string#3}: #3 \\
}

\begin{document}

\newcommand{\mA}{3.1}
\newcommand{\mB}{0}
\newcommand{\mC}{8.2}

\saveSwapValueA{\mA}{\mB}{\mC}

\renewcommand{\mA}{3.1}
\renewcommand{\mB}{0}
\renewcommand{\mC}{8.2}

\saveSwapValueB{\mA}{\mB}{\mC}

\end{document}
  • That was exactly the explanation, in terms of the degree of expansion a command does, that I needed to understand. – Jim Ratliff Aug 18 at 0:15

Your Answer

 

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged or ask your own question.