
실제로 새로운 제어 시퀀스를 생성 합니까 \let
, 아니면 이미 정의된 제어 시퀀스에 포인터를 할당합니까?
크누스는 이렇게 말합니다.
let\cs=<token>
\cs
토큰의 현재 의미를 제공합니다 .<token>
다른 제어 시퀀스인 경우\cs
해당 제어 시퀀스와 동일한 의미를 갖습니다. (텍북 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
총 2개)입니다.
작동 방식은 \let\a<token>
문자 그대로 의 의미를 <token>
제어 시퀀스에 복사하여 가 "실행"될 \a
때마다 마치 거기에 있는 \a
것처럼 정확하게 작동하도록 하는 것 입니다 <token>
. 이 복사는 명령이 수행되는 시점에 수행되므로 \let
몇 번 \a
사용해도 새로운 변경이 이루어지지 않습니다. 게다가 <token>
변경 되면그것은의미(예: 다른 사람을 통해 \let
)의 의미는 \a
영향을 받지 않습니다.
"포인터"라는 용어를 사용하는 것은 어떤 의미에서 부적절합니다. 언어로서의 TeX에는 메모리 모델이 없고, (필수적으로) 구현된 언어가 임의 접근 권한도 없기 때문입니다.그것은메모리 모델은 작동을 이해하는 데 관련 구현의 내부 세부 사항도 아닙니다. 그러나 TeX가 C로 구현되었다고 가정하더라도 토큰에 대한 포인터의 유사점은 다음과 같습니다.
\def\a{<token>}
*\a = <token>
유효한 C 구문이라고 가정하면 다음과 같습니다 . 가상 구문은 *\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}