\expandafter 在 \begingroup 内... \endgroup

\expandafter 在 \begingroup 内... \endgroup

可能重复:
\begingroup\expandafter…\endgroup 起什么作用?

在 Heiko Oberdiek 的许多包装中,我们都能看到这种类型的结构:

\begingroup\expandafter\expandafter\expandafter\endgroup
\expandafter\ifx\csname pdf@filesize\endcsname\relax
  \ifxetex
    ...

\expandafter将命令包含在内的目的是什么begingroup...\endgroup?这种方法有什么优点?

答案1

哦,鬼鬼祟祟的 Heiko:-)

它测试 csname 是否未定义(或放宽),但如果它之前未定义,则它保持未定义状态,因为隐式定义会\relax在组内部发生。

纯 TeX:

\begingroup\expandafter\expandafter\expandafter\endgroup
\expandafter\ifx\csname aaaa\endcsname\relax
\show\aaaa
\fi

\expandafter\ifx\csname bbbb\endcsname\relax
\show\bbbb
\fi


\bye

生成:

(./heiko.tex
> \aaaa=undefined.
l.3 \show\aaaa

? 

> \bbbb=\relax.
l.7 \show\bbbb

? 
 )

答案2

实际上,这与避免哈希表的过度填充有关。

问题在于

\begingroup\expandafter\expandafter\expandafter\endgroup
\expandafter\ifx\csname pdf@filesize\endcsname\relax
  ...
\else
  ...
\fi

是它不可扩展。使用 eTeX,你可以改用\ifcsname。如果你测试的是控制序列而不是名称,你可以改用\ifdefined。但 Heiko 会创建独立于平台的包。

你也可以考虑电子工具箱packages 的定义\csletcs

\newrobustcmd*{\csletcs}[2]{% [2011/01/03]
  \ifcsdef{#2}{\expandafter\let
    \csname#1\expandafter\endcsname
    \csname#2\endcsname}{\csundef{#1}}%
}

期权包将其定义为(此处使用假名):

\def\letnames#1#2{%
  \begingroup\expandafter\endgroup
  \expandafter\let\csname#1\expandafter
  \endcsname\csname#2\endcsname
}

因为无论如何都是不可扩展的。如果最初未定义,\let#1#2未定义。#2

相关内容