What is the difference between the \let
and \def
commands in TeX/LaTeX?
Ideally please provide a simple example that will illustrate the difference between them.
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It only takes a minute to sign up.
Sign up to join this communityThe difference is in the time at which the ‘right hand side’ is evaluated.
Thus \let\foo\bar
defines \foo
to have the value that \bar
had at the point of definition. On the other hand, \def\foo{\bar}
in effect defines \foo
to have the value that \bar
has at the point of use.
Consider:
\def\bar{hello}
\let\fooi\bar
\def\fooii{\bar}
\fooi +\fooii
\def\bar{goodbye}
\fooi +\fooii
This produces
hello+hello
hello+goodbye
This is a simple process.
However it's also a subtle one, so it might be worth highlighting a few key points:
When TeX encounters control sequences such as \fooi
, it evaluates them; if these are macros (that is, they have been defined by \def
, or \let
equal to something which was defined by \def
), then the result is that they will expand to other tokens, which TeX will then examine in turn, and so on, recursively, until what's left is either ‘primitive’ control sequences or letters (I'm simplifying a little bit).
\fooi
expands directly to the characters hello
(because \bar
initially did, and \fooi
was defined to have the same value).
\fooii
, in contrast, expands to \bar
, which is then immediately reexamined and reexpanded. In the first case, \bar
expands to hello
and in the second case to goodbye
. The definition of \fooii
hasn't changed, but \bar
has been redefined in between.
Getting a clear idea of the process of this recursive expansion is very helpful when learning how to develop and debug TeX macros.
\let\foo\bar
is the same as \def\foo{\expandafter\bar}
? Probably not, but why then?
\foo\alpha
at the bottom of the example would expand into \expandafter\bar\alpha
; what that does is first expand \alpha
, and then expand \bar
(in this case to 'goodbye'). Using \expandafter
counts as pretty advanced TeX, and is for the arcane cases where you need to control the order of evaluation in a non-default way. Try TeXing \def\baz{wibble} \def\x#1{-#1-} \x\baz \expandafter\x\baz
Jul 20, 2012 at 11:15
\let\foo\bar
along the lines @Didii is suggesting would be \expandafter\def\expandafter\foo\expandafter{\bar}
. There remain differences even between these, as detailed in Martin Scharrer's answer. But for most purposes, I think they would have much the same effect.
Sep 1, 2014 at 23:15
While the existing answers are all true I like to highlight one point which wasn't explicitly mentioned yet. I myself got this information recently from Joseph Wright (see his answer and our comments in Simple un-obfuscation of some LaTeX internals).
As Michael said \let\macroa\macrob
"copies" the definition of \macrob
to \macroa
. However an IMHO important thing here is that the definition isn't actually copied, i.e. exists twice, but the command sequence \macroa
now points to the same hash table entry as \macrob
.
This means that \let\macroa\macrob
uses less memory space (very important in the early days but not anymore) and is faster then \def\macroa{\macrob}
because in the second form two command sequence names have to be resolved in the hash table.
Also \let
actually "copies" the definition of tokens, which do not need to be macros/command sequences. This allows the definition of command sequences representing implicit characters like \let\bgroup={
.
\bgroup
control sequence doesn't “represent” an implicit character; it is an implicit character (by definition of implicit characters).
\bgroup
is really what DEK calls an implicit character, there is no indirection to follow in order to get from \bgroup
to an implicit character.
They're pretty completely different. \let
copies a command to a new name, while \def
creates a new command.
For example:
\def \foo {bar}
creates a new command \foo
, that evaluates to bar
when run.
\let \foo \bar
copies the commands from the \bar
commands to the \foo
command, so you can call either. Because it's a copy (and not a pointer from one to the other), redefining \foo
won't change the behavior of \baz
. Hence:
\def \foo {bar}
\let \baz \foo
\baz % Outputs 'bar'
\def \foo {new-definition}
\baz % Still outputs 'bar'
\def
, so I'm not surprised I botched the syntax :)
Jul 27, 2010 at 14:34