6

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!

1
  • Most likely: use \let #2 = #1 instead of \renewcommand{#2}{#1}, and so on for the others. Commented Aug 17, 2018 at 23:25

1 Answer 1

10

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}
1
  • That was exactly the explanation, in terms of the degree of expansion a command does, that I needed to understand. Commented Aug 18, 2018 at 0:15

You must log in to answer this question.

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