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.
\edef
expands the argument, whereas \let
doesn't. Here is an example to illustrate the difference:
\def\txt{a}
\def\foo{\txt}
\let\bar\foo
\bar -> a
\def\txt{b}
\bar -> b
However,
\def\txt{a}
\def\foo{\txt}
\edef\bar{\foo}
\bar -> a
\def\txt{b}
\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?
\def\txt{bar}
\def\foo{\txt}
\expandafter\def\expandafter\bar\expandafter{\foo}
\let\BAR\foo
{\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.
Best Answer
Of course, they have different syntax.
\ifx\cyrdash\undefined
is traditional way to test if a macro is undefined. Of course,\undefined
sould not be defined.There are
\ifdefined
and\ifcsname
primitives in eTeX. They have no other side effects.LaTeX's
\@ifundefined
test if a macro is defined or it has the same meaning of\relax
. Furthermore,\@ifundefined{undefinedfoo}{...}{...}
will makes\undefinedfoo
to be\relax
.Normally, there is no difference between
and
eTeX primitives may be a little safer. Say, we don't need to worry about whether
\undefined
is really undefined.However, these two usage are different:
and
In fact,
\csname undefined\endcsname
makes\undefined
to be\relax
, while\ifcsname undefined\endcsname
makes\undefined
unchanged. That's why\ifcsname
in eTeX is necessary.Test code: