7

I would have thought that if I declare \let\stdeqref\eqref, then the \stdeqref macro and the \eqref macro would be interchangeable. But here is an example where it fails! Moreover, this failure is (somehow) caused by the microtype package?! What is going on, and how to fix it?

\documentclass{article}

\usepackage{microtype}

\usepackage{amsmath}

\let\stdeqref\eqref

\begin{document}

\begin{equation}\label{a}
A
\end{equation}

This is good spacing: \eqref{a}\allowbreak\eqref{a}

This is bad spacing: \stdeqref{a}\allowbreak\stdeqref{a}

But the bad spacing becomes good if we remove microtype!

\end{document}

enter image description here

The reason I'm asking is that I would like to redefine the \eqref macro in a way which uses the usual \eqref macro as a subcomponent, via the usual strategy I've seen time and time again on this site:

\let\stdeqref\eqref
\renewcommand\eqref[1]{Something fancy containing \stdeqref{#1} etc.}

but that doesn't work anymore if \let isn't behaving as expected . . .

8
  • \let is generally not usable on latex-defined commands, hence \NewCommandCopy Commented yesterday
  • @DavidCarlisle I just tried it with \NewCommandCopy in place of \let and the behavior is the same (that is, has the same seemingly incorrect behavior) :/ Commented yesterday
  • 1
    yes but \let doesn't save the original definition so isn't usable for the renewcommand kinds of use that you indicate are the end use case. Commented yesterday
  • 1
    you don't say what is bad about the spacing, it looks OK to me? I added an image Commented yesterday
  • 1
    oh you should have said you have tl2022 (so are missing three years worth of bug fixes) Commented yesterday

2 Answers 2

8

egreg's answer gives the right fix, but doesn't explain why you get the 'bad' spacing when you use \let in the preamble for older (and only older) TeX Live. Indeed, the console output there (for TL 2025) corresponds to output which doesn't demonstrate the problem raised in the question.

For current LaTeX, using \let in the preamble actually avoids the bad spacing, but it does so in a way you probably do not want.

\documentclass{article}
\usepackage{microtype}

\usepackage{amsmath}
\let\stdeqref\eqref

\begin{document}

\ShowCommand\eqref
\ShowCommand\stdeqref

\begin{equation}\label{a}
A
\end{equation}

This is good spacing: \eqref{a}\allowbreak\eqref{a}

This is bad spacing: \stdeqref{a}\allowbreak\stdeqref{a}

But the bad spacing becomes good if we remove microtype!

\end{document}

With current LaTeX, we have

> \eqref=robust macro:
->\protect \eqref  .

> \eqref =\long macro:
#1->\textup {\@nameuse {MT@patch@saved@\string \tagform@ }{\ref {#1}}}.
<argument> \eqref  
                   
l.510 \ShowCommand\eqref
                        
? 
> \stdeqref=macro:
->\protect \eqref  .
<argument> \stdeqref 
                     
l.511 \ShowCommand\stdeqref
                           
? 

So \stdeqref is defined as the \protect\eqref . That is not a good idea at all if you plan to redefine \eqref. If you redefine it to not be robust, you may retain the original definition, but that would be more by luck than judgement. You do not really want the 'inner' \eqref to diverge from the outer, protected \eqref.

But you do not get the 'bad' spacing here because the inner \eqref is untouched.

If, however, we go back to (updated) TeX Live 2021, we find something different:

> \eqref=\long macro:
#1->\textup {\@nameuse {MT@patch@saved@\string \tagform@ }{\ref {#1}}}.
<argument> \eqref 
                  
l.510 \ShowCommand\eqref
                        
? 
> \stdeqref=\long macro:
#1->\textup {\tagform@ {\ref {#1}}}.
<argument> \stdeqref 
                     
l.511 \ShowCommand\stdeqref
                           
? 

Here, we see the timing effect egreg described, which results in the different spacing. This happens because \eqref is not defined as robust here, so there is no 'inner' \eqref . \eqref is just a common-or-garden unprotected macro. As such, \stdeqref gets \let to the same thing and, if this is done in the preamble, microtype's patch is then applied to \eqref but not, of course, \stdeqref.

The reason microtype patches \eqref is because it changes some of the macros \eqref uses. If we compare the pre- and post-amble definitions of \tagform@ when microtype is used, for instance, we find:

> \tagform@=macro:
#1->\maketag@@@ {(\ignorespaces #1\unskip \@@italiccorr )}.
<argument> \tagform@ 
                     
l.508 \ShowCommand\tagform@
                           
? 
(/usr/local/texlive/2021/texmf-dist/tex/latex/l3backend/l3backend-pdftex.def)
(./prawf-1.aux)
(/usr/local/texlive/2021/texmf-dist/tex/latex/microtype/mt-cmr.cfg)
> \tagform@=macro:
#1->\maketag@@@ {\leftprotrusion {(}\ignorespaces #1\unskip \@@italiccorr \righ
tprotrusion {)}}.
<argument> \tagform@ 
                     
l.514 \ShowCommand\tagform@
                           

That is, when you copy the preamble definition of \eqref, you get a definition which uses a patched version of \tagform@ but is not itself patched to work correctly with this.

To see this is what's happening, you can try:

\documentclass{article}
\usepackage{microtype}

\usepackage{amsmath}
\let\stdeqref\eqref
\makeatletter
\let\stdtagform@\tagform@
\makeatother

\begin{document}

\makeatletter
\newcommand\ostdeqref[1]{%
  {\let\tagform@\stdtagform@\stdeqref{#1}}%
}
\makeatother

\begin{equation}\label{a}
A
\end{equation}

This is good spacing: \eqref{a}\allowbreak\eqref{a}

This is bad spacing: \stdeqref{a}\allowbreak\stdeqref{a}

This is good spacing: \ostdeqref{a}\allowbreak\ostdeqref{a}

But the bad spacing becomes good if we remove microtype!

\end{document}

three cases

That is, we get bad spacing only when we use a non-patched copy of \eqref with a patched copy of \tagform@. If both or neither are patched, the problem does not occur.

With newer versions of TeX Live, we get the both-patched scenario, essentially by chance, because \let is not really copying the 'inner' definition, as \eqref is now defined as robust.

7

It's a timing problem. If I do

\documentclass{article}
\usepackage{microtype}
\usepackage{amsmath}

\ShowCommand\eqref

\begin{document}

\ShowCommand\eqref

\stop

I get

> \eqref=robust macro:
->\protect \eqref  .

> \eqref =\long macro:
#1->\textup {\tagform@ {\ref {#1}}}.
<argument> \eqref

l.5 \ShowCommand\eqref

?
(/usr/local/texlive/2025/texmf-dist/tex/latex/l3backend/l3backend-pdftex.def)
(./pardon.aux)
(/usr/local/texlive/2025/texmf-dist/tex/latex/microtype/mt-cmr.cfg)
> \eqref=robust macro:
->\protect \eqref  .

> \eqref =\long macro:
#1->\textup {\@nameuse {MT@patch@saved@\string \tagform@ }{\ref {#1}}}.
<argument> \eqref

l.9 \ShowCommand\eqref

?

So you see that microtype changes the definition of \eqref at begin document and you should do the redefinition (I guess you don't just want to get an alias to \eqref) at begin document.

Ensure to do

\AtBeginDocument{\NewCommandCopy{\stdeqref}{\eqref}}

in order to have an alias so you can redefine \eqref to your liking in terms of \stdeqref. Using \let on a robusted command is, to say the least, risky.

Some more details

If you do \let\stdeqref\eqref, the meaning of \stdeqref becomes \protect\eqref• (where the bullet means a space in the control sequence name). As we've seen, microtype redefines \eqref• and so, if you call

\stdeqref{a}\allowbreak\stdeqref

you get a result that's exactly the same as \eqref{a}\allowbreak\eqref{a}. Indeed, this is what happens:

\documentclass{article}
\usepackage{microtype}
\usepackage{amsmath}

\let\stdeqref\eqref

\begin{document}

\begin{equation}\label{a}
A
\end{equation}

\eqref{a}\allowbreak\eqref{a}

\stdeqref{a}\allowbreak\stdeqref{a}

\end{document}

same result

To the contrary, if you do \NewCommandCopy{\stdeqref}{\eqref}, you get

different result

Why? Because \NewCommandCopy defines \stdeqref to be \protect\stdeqref• and copies \eqref• into \stdeqref•, so the microtype patch isn't applied when you use \stdeqref{a}. Of course this is wrong and, as said, you should do

\AtBeginDocument{%
  \NewCommandCopy{\stdeqref}{\eqref}%
  % the redefinition of \eqref using \stdeqref goes here
}
2
  • Unrelated, but why is \letting a robust command risky? We often see constructs like \cs_new_protected:Npn \__foo: { foo } followed by \cs_gset_eq:NN \foo \__foo:. Isn't it the same? Commented yesterday
  • @Niranjan See tex.stackexchange.com/a/47372/4427. It has to do with robust command, not with protected ones. Commented 23 hours ago

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.