14

I've seen people writing things like

\let\original@somemacro=\somemacro

while I usually write

\let\original@somemacro\somemacro

Is there any difference between them?

(I believe this question must have been asked somewhere else on this site, but was not able to find it.)

Jinwen
  • 8,518

2 Answers2

17

You can be pretty safe doing things explicitly because you know the values of the components in advance, but in code (i.e., macros) where you may not know what the user may wish to assign, you can get burned if you do not use the = as part of the assignment. Therefore, it is a good habit to use it.

Consider this case that misbehaves without the = in the \let assignment:

\documentclass{article}
\begin{document}
\def\doit#1{\let\X#1}

\doit{=} what?

\X oops \end{document}

enter image description here

Compare it to the output, when the = is added to the \let syntax. Ah, much more expected:

\documentclass{article}
\begin{document}
\def\doit#1{\let\X=#1}

\doit{=} what?

\X much better \end{document}

enter image description here

Here's another case to highlight the difference:

\documentclass{article}
\begin{document}
\def\deftok#1#2{\let#1= #2\empty}

\deftok\W{ }

\W success

\def\deftok#1#2{\let#1=#2\empty}

\deftok\W{ }

\W fail

\def\deftok#1#2{\let#1 #2\empty}

\deftok\W{ }

\W fail \end{document}

enter image description here

In this example, not only is the = imperative, but so is the space following the =, if you wish to do assignments of spaces. The syntax also allows \deftok\W{} to assign \empty to \W.

So in summary, spaces and = tokens can be problematic assignments with \let and care must be exercised. I learned this lesson the hard way in V1.1 of my tokcycle package. "Once burnt, twice learnt!"

  • So, is it a good habit to always add the =? – Jinwen Mar 03 '21 at 01:41
  • 2
    @Jinwen In general code, especially if to be used by others, absolutely yes. In one-off assignments, used locally and discarded, you will know if the absence of the = is OK. – Steven B. Segletes Mar 03 '21 at 01:44
  • 2
    @Jinwen In case you wish to be able to assign the meaning of space-token, too, then it is a good habit to add =, i.e., =<space>, because with \let-assignments after = one is discarded. – Ulrich Diez Mar 03 '21 at 11:43
11

The previous answer shows why = is usable to use it in \let syntax. Another argument is "more clarity".

I show different view, i.e. a case where usage of = is somewhat impractical in \let syntax: when the second token of \let is constructed by \csname...\endcsname. The following example is wrong:

\let\foo = \csname bar\endcsname

because \let scans its parameters without expansion: the example above does \let\foo=\csname and the bar\endcsname follows with the error when \endcsname is processed. So, we must use the \expandafter chain:

\expandafter\let \expandafter\foo \expandafter=\csname bar\endcsname

We can spare one \expandafter if we do not use = here:

\expandafter\let \expandafter\foo \csname bar\endcsame

If both tokens scanned by \let must be constructed by \csname...\endcsname pair then we can use another trick with "\expandafter started inside \csname...\endcsname pair":

\expandafter\let \csname foo\expandafter\endcsname \csname bar\endcsname

In old macros, the = from \let syntax was not used in macro bodies because it spares one token in the TeX memory. But this is irrelevant today.

wipet
  • 74,238
  • 3
    This is why expl3 allows \cs_set_eq:NN \foo \bar, \cs_set_eq:Nc \foo {bar}, \cs_set_eq:cN {foo} \bar and \cs_set_eq:cc {foo} {bar} – egreg Mar 03 '21 at 09:14
  • We are using TeX primitive constructs and we have no problems. There are few basic and well known "cubes from the kit" at TeX primitive level. We need not to know plenty another control sequences from expl3. – wipet May 25 '22 at 04:18