Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

Does \let really create a new control sequence, or does it just assign a pointer to an already defined control sequence?

Knuth says that:

let\cs=<token> gives \cs the token's current meaning. If the <token> is another control sequence, \cs will acquire the same significance as that controle sequence. (TeXbook 206)

Suppose I define a new list environment bars in which \bar is just another name for \item:

\newenvironment{bars}
{\begin{enumerate}\let\bar\item}
{\end{enumerate}}

and then use that environment 1000 times in my document as follows:

\begin{bars}
\bar bla bla
\bar bla bla bla
\end{bars}

How many locations in memory end up having the same content as \item when I compile my document? 1, 2, or 1001?

share|improve this question
3  
While inside the environment there will be two (\item and \bar) but between the environments (and at the end of the document) there will be only one. Outside the environment, \bar will revert to its normal meaning. Tip: end of log file tells you memory usage. –  Andrew Kepert Apr 14 '13 at 2:38

2 Answers 2

up vote 5 down vote accepted

The answer to your question is "one more", i.e. \item and \bar (so, two total).

The way \let\a<token> works is by literally copying the meaning of <token> into the control sequence \a, so that whenever \a is "executed" it acts exactly as though <token> were there. This copying is done at the time of the \let instruction, so that no matter how many times \a is used, no new changes are made; furthermore, if <token> changes its meaning (say, through another \let), the meaning of \a is unaffected.

Your use of the term "pointer" is inappropriate in a sense, since TeX as a language doesn't have a memory model, nor does (necessarily) the language in which it's implemented have random access to its memory model, nor are the internal details of its implementation relevant to understanding its operation. However, even assuming that TeX were implemented in (say) C, the analogue of a pointer to a token would be

\def\a{<token>}

which would be like *\a = <token>, assuming that were valid C syntax. The imaginary syntax *\a = *<token> corresponds to \let\a<token>, while the syntax *\a = <token>, although similar to the first one, would actually define \a in such a way that doing \def\a{<other token>} would redefine <token>, which is not possible in TeX. So there isn't really an exact analogue to pointers in TeX.

share|improve this answer
    
The problem is not just how many times \a is used, but how many times a new \a is defined by occurrences of an environment that include a new \let\a<token> each. –  nicolai.rostov Apr 14 '13 at 5:20
1  
Oh, I see. The answer is still "two", but only inside one of the environments. Outside, \bar will retain its original meaning (probably undefined). –  Ryan Reich Apr 14 '13 at 14:23

Although TeX can store multiple versions of a given macro, local to a { } group, it is generally quite hard to fill up the memory, as the memory is reclaimed and reused once the group is left (this was the basis of my original comment). Most environments such as itemize include such grouping. When an existing command is \def'd or \let'd to be something else inside a group, the old version is saved (stacked) and restored at the end of the group.

None of the standard constructions will generate much "stack" wastage, unless you manage some infinite recursion of nested groups or similar.

Generating a large finite number of nested groups with different definitions of a given macro can be done, but you have to be a bit devious:

\documentclass[a5paper,12pt]{article}
\usepackage[margin=20mm]{geometry}

%% version of plain TeX \loop that uses global macros
\def\gloop#1\repeat{\gdef\body{#1}\giterate}
\def\giterate{\body \global\let\next\giterate \else\global\let\next\relax\fi \next}
\let\repeat=\fi % this makes \loop...\if...\repeat skippable

\begin{document}

\raggedright

\section*{Ascending}
\newcount\n
\global\n=0

\gloop
  \ifnum \n<100
  \bgroup
  \edef\foo{\the\n}
  \let\baz=\foo
  \global\let\foobar=\baz
  $\foo^{\baz}_{\foobar} \uparrow$ 
  \global\advance\n 1
\repeat

\section*{Descending}

\global\n=0
\gloop
  \ifnum \n<100
  $\foo^{\baz}_{\foobar} \downarrow$ 
  \egroup
  \global\advance\n 1
\repeat

\end{document}

enter image description here

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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