12

I've already looked at at least ten different q&as explaining the differences of a subset of the commands listed above. While experimenting with them and trying to understand the subtle differences between them, I came up with a simple formula for each command. Here is my take on them. If they are incorrect or there is more detail that one should know, please correct me.

Code: Behavior at definition

\let\a\b: \a points to (\b expanded once)

\def\a{\b}: \a points to \b, no expansions at all

\edef\a{\b}: \a points to (\b expanded recursively until no expansions are possible)

\gdef\a{\b}: same as \def\a{\b} but global

\xdef\a{\b}: same as \edef\a{\b} but global

\newcommand\a{\b}: same as \long\def\a{\b} but raises error if \a already exists, \newcommand* to remove \long

\renewcommand\a{\b}: same as \long\def\a{\b} but raises error if \a does not exist

\providecommand\a{\b}: same as \long\def\a{\b} but does not overwrite if \a already exists

user202729
  • 7,143
mbly82553
  • 121
  • 2
  • 1
    The first is slightly wrong: there is no expansion involved. With \let\a\b, the control sequence \a gets the current meaning of \b. If \b is a macro, then also \a becomes a macro, but \b needn't be a macro. Later redefinitions of \b won't change the meaning of \a. To the contrary, with \def\a{\b}, \a is a macro that expands to \b (and the current meaning of \b will be used). When \b is a macro, the effect of \let\a\b could be described as “define \a to be a macro whose expansion is the same as the current expansion of \b”, but \let is much more general. – egreg Oct 25 '22 at 08:46
  • By the way the first half are explained in TeXbook or TeX by topic, the second half is in LaTeX (unofficial) reference manual (or the LaTeX book if you prefer). See also package writing - Where do I start LaTeX programming? - TeX - LaTeX Stack Exchange Better just spend some time read through them, LaTeX is quite unintuitive so if you want to program in it be careful or it will bite you back later. – user202729 Oct 25 '22 at 09:26
  • 1
    Try for example \let\test=C \meaning\test to see what egreg means. ;) – Weißer Kater Oct 25 '22 at 09:45
  • Languages like C asigns variables to fixed locations in memeory, and pointers are variables that contain an address of another variable. With languages like TeX and Matlab, ALL "variables" are pointers (or data structures containing catcode/data type as well). – John Kormylo Oct 25 '22 at 13:02
  • @JohnKormylo What do you mean by 'ALL "variables" are pointers'? Particularly w.r.t. those whose value may be varied using \setlength? – Rosie F Oct 26 '22 at 07:01
  • Any command name can refer to any macro, register or primitive. Macros (strings) actually consist of linked lists of character nodes. When you define a new macro, or redefine an old macro, it creates a new linked list from the free nodes. When a string is no longer used, it is returned to the list of free nodes. – John Kormylo Oct 26 '22 at 15:15
  • Off topic, but with matlab you can create an array where every element is a different data type, including text and other arrays. You can swap them out dynamically. – John Kormylo Oct 26 '22 at 15:22

2 Answers2

8

Mostly correct, but misleading.

You can use \let to assign a meaning to a control sequence or active character and

\let\a=<token>

will assign \a the same meaning as <token> has at the time when \let is executed. The = is optional as are single space tokens around it (the = is essentially mandatory only if you want to do \let\a==).

If you do \let\a\b when \b is a macro, then also \a will be a macro; both macros will have the same first level expansion and, moreover, \a won't change its meaning if \b is later redefined. However, \let is much more general and the <token> can actually be any token, either explicit or symbolic.

If you do \let\a=a, then \ifx\a a, \if\a a and \ifcat\a a will all return true.

So your description of \let is correct only when \b is a macro, and that's why I say it's misleading: control sequences may not be macros! You can do

\let\a\relax
\let\a\pi
\let\a\pageno

(I'm talking plain TeX here) and in no case \a would be a macro, but rather an unexpandable token. So you see that no expansion can actually be involved when \let is concerned.

What's the difference between \let\a\b and \def\a{\b}? A big one. In the first case \a need not be a macro, depending on the meaning of \b; in the second case \a is a macro, whose expansion is \b: when TeX is doing macro expansion and finds \a, it will replace it by \b and proceed expanding \b (if it's an expandable token) or executing it.

The other descriptions are good, but hide the important fact that the replacement text in \def and friends can be any token list.

David Carlisle
  • 757,742
egreg
  • 1,121,712
  • 1
    probably also worth mentioning that \edef can error: "expanded recursively until no expansions are possible" hides a multitude of issues – David Carlisle Oct 25 '22 at 10:48
6

If you try to fully understand \let (this one is wrong specified in your question) then imagine, that TeX manages a dictionary of all used control sequences and catcode-active letters. Each item in this dictionary includes a pointer to another memory structure in TeX, where the meanig of the control sequence is implemented. This meaning can be:

  • a TeX primitive,
  • a register (a primitive register like \hsize or a register given by \countdef, \dimendef, etc.)
  • a macro,
  • a font switcher,
  • a (math)character constant,
  • a character token given by its catcode/code.

When you say \let\a=\b then TeX inserts the \a to the dictionary of the control sequences (only if it is not here already) and sets its pointer to the same pointer as have \b in the dictionary. If \b isn't in the dictionary, then \a is removed too (i.e. undefined control sequence).

On the other hand, \def\a{...} creates a new memory structure for given macro (i.e. reads parameter text and its body and saves them). Moreover, it puts \a to the dictionary of the control sequences (only if it is not here already) and set its pointer to the newly constructed memory structure where the full meaning of the macro is saved a while ago.

Why your specification of \let is wrong even if \b is a macro: suppose a macro \b with parameters. Then expansion of \b must read real parameters and substitute them in the places where #1, #2 occur in the macro body. Nothing from this is done when \let is processed.

wipet
  • 74,238