[Tex/LaTex] Why is \global\let not always global

amsmathgrouping

As an LaTeX environment opens a local group, it is normally necessary to use a global definition if changes in the environment should be available after the environment:

\documentclass{minimal}
\usepackage{amsmath}
\begin{document}
    \begin{multline}
        \gdef\mylabel{text}
    \end{multline}
    \show\mylabel
\end{document}

This results in:

> \mylabel=macro:
->text.

Unfortunately, this does not work with a \global\let. Locally, the definition is correct, as in the following example:

\documentclass{minimal}
\usepackage{amsmath}
\begin{document}
    \begin{multline}
        \global\let\mylabel\label
        \show\mylabel
    \end{multline}
\end{document}

This results in:

> \mylabel=macro:
#1->\begingroup \measuring@false \label@in@display {#1}\endgroup .

There is no global effect:

\documentclass{minimal}
\usepackage{amsmath}
\begin{document}
    \begin{multline}
        \global\let\mylabel\label
    \end{multline}
    \show\mylabel
\end{document}

This results in:

> \mylabel=\long macro:
#1->.

Why is the \global\let not global here? Is there some (general) work-around to get a \global\let?

Solution (thanks to David Carlisle):

David Carlisle is correct. As amsmath calls the environment twice and the \label command is deleted after the first call, we end up with a deleted command. The solution is to avoid resetting the command in the second call:

\documentclass{minimal}
\usepackage{amsmath}
\usepackage{etoolbox}
\begin{document}
    \begin{multline}
        \ifundef{\mylabel}{%
            \global\let\mylabel\label
        }{}%
    \end{multline}
    \show\mylabel
\end{document}

Best Answer

AMS alignments are executed twice internally, a first pass to measure the fields and a second pass to typeset. \label is given a null definition the second time to avoid duplicating writes to the aux file which would generate errors.

So you do a global let of the real definition but you don't see it as you globally let to the null definition on the second pass.

You can see this by putting \show\mylabel inside your multline and see it reporting two values. You can use the \ifmeasuring@ switch to test which pass you are on. and just do the let on one of them.

\documentclass{minimal}
\usepackage{amsmath}


\begin{document}

\makeatletter
    \begin{multline}
  \ifmeasuring@
        \global\let\mylabel\label
    \show\mylabel
\fi
    \end{multline}
    \show\mylabel
\end{document}

Produces

> \mylabel=macro:
#1->\begingroup \measuring@false \label@in@display {#1}\endgroup .
l.14     \show\mylabel