[Tex/LaTex] \let\foo\bar vs \let\foo=\bar (let with equals sign)

tex-core

Both uses of the \let primitive often lead to the same result. Is this even true for every case? What was the thought process behind it. And if they are actually not equivalent, are there particular situations in which you can only use one or the other?

Addendum

Summary

As your plenty and nice answers show, there are cases in which you clearly have to respect one of the variations (for instance regarding assignments to '=' and macros that check for spaces). These were totally understandable points and they explain a lot. Now, @Werner's answer confirmed one ingenuous thought of mine:

"The use of = is purely to emphasize the fact that an assignment is being made […]"

Moreover Knuth himself seem to have intended the synopsis including the '=', though he also used the other way. Why did he include it then? It will probabilly have to do with the exact meaning of the TeX source snippet cited by @Werner. To be honest, I don't know WEB either, but if there is someone who does, can he explain it (in very easy terms) by adding an edit to his answer? New answers are clearly welcome too.

Side Note

As an element of a gray area I found an example where using the syntax including the equal sign causes "difficulties":

If you have control sequences which need the 'csname-expandafter' mechanism, and you want to stick to the minimal exploitation of \expandafter by saying

\expandafter\let\csname foo1\expandafter\endcsname\csname bar1\endcsname

you can't add an equal sign because it would distract TeX from reading the \expandafters correctly. To get the equal sign work you would need to use the slightly unhandier version

\expandafter\let\csname foo1\expandafter\endcsname\expandafter=\csname bar1\endcsname

Best Answer

There is a case where = is mandatory, besides the obvious one when you want to \let a token to be the same as =:

\let\equals==

is the only correct form.

The syntax rules for \let are

\let<control sequence><equals><one optional space><token>

where only <equals> requires an explanation: it is

<optional spaces> | <optional spaces>=

where = must have category code 12 (and be explicit). Note that no expansion is attempted during a \let assignment, so the optional spaces must be explicit. The following example should not be taken seriously, but it works:

\edef\four{\space\space\space\space}
\expandafter\let\expandafter\cs\four= \relax

would make \cs equivalent to \relax. This is admittedly esoteric.

However there's a place where the = and the following optional space are mandatory rather than optional.

Suppose we want a macro that tests if the first token in its argument is a space and takes some action if it is. In the following example, the space will be removed.

\documentclass{article}
\usepackage[T1]{fontenc}

\makeatletter
\def\foo#1{\afterassignment\@checkspace\let\next= #1}
\def\@checkspace{%
  \if\noexpand\next\@sptoken
    \typeout{Space found and removed}%
  \else
    \typeout{Space not found}\next
  \fi}
\makeatletter

\begin{document}
|\foo{No space}|
|\foo{ A space}|
|\foo{~ isn't a space}|
\end{document}

enter image description here

The terminal output will be

Space not found
Space found and removed
Space not found

If only \let\next is used, a space would indeed be removed because of the syntax rules, but we'd not be able to distinguish if a space was there or not; worse, if the token list begins with = we'd be in big trouble. With \let\next= and no space, a leading = would be honored, but still an initial space would be removed with no notice.

There are other methods, for example with \futurelet, to solve the same problem. One might enjoy looking at how booktabs.sty defines \futurenonspacelet using a trick similar to this one.


Actually Knuth is quite coherent in his usage of the optional = in plain.tex. All top level \let instructions have it, because this can only impact by a few microseconds in the processing of the instruction, while inside definitions the = is rarely used. It appears in the definition of

\alloc@
\newinsert
\newif

but in all the other replacement texts it's omitted, because it impacts on memory usage: each token in a replacement text occupies space and, when TeX was developed, memory space was a concern.

Conversely, in manmac.tex all \let instructions have = (except, quite strangely, in the definition of \footnote). The difference is that, in case memory is scarce when typesetting the TeXbook, manmac.tex can be easily edited, while plain.tex is “for everybody” and so must be optimized.

Related Question