204

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.

219

The 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.

  • 1
    Does this mean that \let\foo\bar is the same as \def\foo{\expandafter\bar}? Probably not, but why then? – Didii Jul 20 '12 at 9:59
  • 2
    With that definition, writing \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 – Norman Gray Jul 20 '12 at 11:15
  • 3
    The closest analogue to \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. – dubiousjim Sep 1 '14 at 23:15
  • 1
    Here is some more discussion. – dubiousjim Sep 2 '14 at 3:42
  • 1
    @NicholasHamilton It's a similar idea, yes, but that may be a slightly confusing way to think about it, since TeX is rather sui generis in programming language terms. A useful mental model is that TeX macros expand, and the expansion is than expanded, and... so on until the engine arrives at one of the relatively small number of primitives which actually do something, such as adding a box (possibly containing a letter or a paragraph) to a list of boxes. Lower-level TeX programming, and its headaches, is all about controlling what gets expanded when, and to what. – Norman Gray May 3 '15 at 15:26
46

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={.

  • According to the TeXbook p. 269, the \bgroup control sequence doesn't “represent” an implicit character; it is an implicit character (by definition of implicit characters). – frougon Jul 18 at 13:37
  • @frougon: Not sure what your exact point is here. I don't see a real difference between represents and is in this context. I could also have written "makes it an implicit character" or similar. Keep in mind that not all users here are native English speakers. – Martin Scharrer Jul 18 at 13:45
  • No offense intended, I myself am not a native English speaker. “Represents” implies “is not really”, IMHO. But here, \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. – frougon Jul 18 at 13:49
22

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'
  • Your \def statements are missing braces, and remember that unless 'bar' is a primitive then TeX expands the material rather then executing it. Good answer, though: more or less what I've have put. – Joseph Wright Jul 27 '10 at 6:10
  • @Joseph Ah yes, fixed; I never actually use \def, so I'm not surprised I botched the syntax :) – Michael Mrozek Jul 27 '10 at 14:34
  • 3
    'pretty completely'... lol, why don't you say 'pretty almost sometimes definately always partially never certainly similar but different' – Nicholas Hamilton Jun 29 '16 at 1:29

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.