\let 使用指针吗?

\let 使用指针吗?

它是否\let真的创建了一个新的控制序列,还是仅仅将一个指针分配给已经定义的控制序列?

Knuth 说道:

let\cs=<token> 给出\cs标记的当前含义。如果<token>是另一个控制序列,\cs将获得与该控制序列相同的意义。(TeXbook 206)

假设我定义了一个新的列表环境bars,其中\bar只是的另一个名称\item

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

然后在我的文档中使用该环境 1000 次,如下所示:

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

内存中有多少个位置最终具有与\item我编译文档时相同的内容?1、2 还是 1001?

答案1

您的问题的答案是“再来一个”,即\item\bar(因此,总共两个)。

该方法\let\a<token>的工作原理是将 的含义逐字复制<token>到控制序列 中\a,这样每当\a被“执行”时,它的行为就和 一样<token>。此复制是在指令执行时完成的\let,因此无论 被使用多少次\a,都不会产生新的变化;此外,如果<token>更改它是意思(比如,通过另一个\let),的意思\a不受影响。

你对“指针”一词的使用在某种意义上是不恰当的,因为 TeX 作为一种语言没有内存模型,并且(必然)它所实现的语言也不能随机访问它是内存模型,其实现的内部细节也与理解其操作无关。然而,即使假设 TeX 是用(比如说)C 实现的,指向 token 的指针的类似物也是

\def\a{<token>}

假设 是有效的 C 语法,则其结果类似于*\a = <token>。虚语法*\a = *<token>对应于\let\a<token>,而语法*\a = <token>,虽然与第一个语法类似,但实际上会这样\a定义:\def\a{<other token>}重新定义 <token>,这在 TeX 中是不可能的。因此 TeX 中并没有与指针完全类似的对象。

答案2

尽管 TeX 可以存储给定宏的多个版本(局部于 { } 组),但通常很难填满内存,因为一旦离开组,内存就会被回收并重新使用(这是我最初评论的基础)。大多数环境(如 itemize)都包含此类分组。当现有命令被 \def'd 或 \let'd 为组内的其他内容时,旧版本将被保存(堆叠)并在组末尾恢复。

除非您管理嵌套组或类似物的无限递归,否则任何标准构造都不会产生太多的“堆栈”浪费。

可以生成大量具有给定宏的不同定义的嵌套组,但你必须有点狡猾:

\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}

在此处输入图片描述

相关内容