When you write


the results are often identical. What is the difference between these two commands? When do they behave the same? When do they not?

(The question isn't for me; inspired by this question comparing \let and \def, I'm asking this question so it can be used as a reference to point people towards in the future.)

  • Slightly off-topic, but note that you may not get what you expect with edef: ``` \count1=0 \def\resA{\count1=10 \the\count1} \edef\resB{\count1=10 \the\count1} ``` At definition time \the\count1 can be expanded, but (it seems) the assignment cannot. Thus, while both macros assign 10 to \count1 \resB will produce a 0 in the output. Commented Jan 4, 2021 at 15:10
  • Yes, that is correct. It is known that counter assignments (assignments in general) are not expandable, so they do nothing inside an \edef. \the\count1, on the other hand, is expandable and expands to the value of the counter (which at the time the \edef is executed, is zero because the assignment in the \edef wasn't carried out). I'm afraid this doesn't quite answer the question, so it would be better suited as a comment Commented Jan 4, 2021 at 16:33

4 Answers 4


\edef expands the argument, whereas \let doesn't. Here is an example to illustrate the difference:

\bar -> a
\bar -> b


\bar -> a
\bar -> a

There are also other differences, say, the arguments and so on. But how to expansion may be the most important(?).

This is an interesting question. May I expand the question further more?

What is the difference between \let and \expandafter\def\expandafter\foo\expandafter ? Do they always behave the same?


{\tt \string\bar = \meaning\bar}\par
{\tt \string\BAR = \meaning\bar}

Sneaky inline answer to this rhetorical question, since I wrote the original question :)

If you are doing this on macros that take no arguments, then the difference between them is negligible. OTOH, you cannot use the \expandafter\def... construct if you're trying to copy the definition of a macro that takes arguments.

In fact, this brings to light one of the aspects that I was hoping people would discuss here. \let creates a literal copy of a macro at the instant that it is executed, whereas \edef will take the contents of the macro and expand it recursively to create a new macro entirely. When you are only using the macros as places to store data (such as \def\name{Will}) then the differences are largely inconsequential, but when the macros are being used as ‘functions’ that take arguments or have contents that have various expansion restrictions applied to it (with \protected, \noexpand, and so on) then the differences can be very important indeed.

  • 5
    \let\foo\bar and \ea\def\ea\foo\ea{\bar} (where \ea is short for \expandafter) are the same if and only if \bar is a parameterless macro which is not \long, \outer or \protected. So, for example, if we do \newcommand{\bar}{Leo} and \ea\def\ea\foo\ea{\bar}, \foo and \bar will not be the same as far as \ifx is concerned, while with \let\foo\bar they will.
    – egreg
    Commented Jun 29, 2011 at 23:33

As already has been said \edef expands its argument. This not only mean that the content will be different to a definition with \let, it also means that the argument must be expandable. You can always do a \let\a\b but e.g. \edef\a{\tableofcontents} will break. Also \edef expands its argument, it doesn't execute them. So things like this will not work:


The main difference is that \let creates a new reference (a.k.a. name) to an existing value while \def (and friends) creates a completely new value and name pair. If you can get yourself to think of names and values as separate things, then the difference between the two primitives is fairly easy to understand (in my opinion).

  • 3
    And if you can't manage to think of names and values as different things, you're not going to get very far with TeX macro programming. (I was going to say "you're going to have trouble", but then I remembered that everyone has trouble...)
    – SamB
    Commented Mar 9, 2012 at 18:47

Beyond the other answers, let me spell out one key point that the question and other answers show implicitly.

Assume that \b is a parameterless macro, whose expansion might contain \c, say:

\def\b{Hello \c !}

We must distinguish (one-step) expansion from recursive expansion: after \def\a{\b}, expanding \a gives token list \b, but the recursive expansion of \a coincides with the recursive expansion of \b (here, Hello Alice!). Since we deal with contexts that do not recursively expand their arguments (unlike paragraph bodies), the distinction matters.


  1. \def\a{\b} makes \a's expansion equal to \b, so redefining \b affects the recursive expansion of \a.
  2. \edef\a{\b} makes \a's expansion equal to \b's recursive expansion, which is usually* a list of non-macro tokens — if so, no redefinition affects the (recursive) expansion of \a.
  3. \let\a\b makes \a's expansion equal to \b's expansion, so redefining \b does not affect \a, as with \edef (examples). But anything affecting \b's expansion (say, redefining \c) still affects \a — unlike with \edef.

*EDIT: @egreg points out that \noexpand is an exception — it allows a recursive expansion to contain unexpanded macros. Details in https://tex.stackexchange.com/a/519/1340.

  • As I'm learning this material recently, beware possible errors and feel free to point them out. Commented Jul 26, 2017 at 17:32
  • 2
    The replacement text of a macro defined with \edef can contain other macros, if they are prefixed by \noexpand.
    – egreg
    Commented Jul 26, 2017 at 17:36
  • @egreg Thanks! Tried to acknowledge that—hopefully the answer's now correct. Commented Jul 26, 2017 at 18:02

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .