\detokenize 的确切语义是什么?

\detokenize 的确切语义是什么?

怎么\detokenize運作?

e-TeX 简短参考手册指出:

当后面跟着一个 时<general text>,会扩展为产生一个字符标记序列,该序列由\catcode10 个字符(空格)或 12 个字符(其他)组成,对应于 <balanced text>未扩展的 的 标记的分解<general text>;参见\showtokens。效果就像是 在只有 10 和 12 的范围内 \scantokens应用于。请注意,为了保留控制字和任何后续字母之间的边界,每个控制字(包括最后一个控制字)后都会产生一个空格。<general text>\catcodes

用简单的英语来说这是什么意思?我想理解这段代码:

\def\task#1{\@task#1::\@nil}
\def\@task#1:#2:#3\@nil{%
  \if\relax\detokenize{#2}\relax
  ...

我认为\task被定义为一个宏,它接受一个参数,并调用\@task。我不知道这是什么\@nil意思——它可能用于结束宏调用。我也不知道\relax\detokenize做什么,但 detokenize 接受 参数的第二部分task macro(各部分用分号分隔)。

答案1

\task接受一个参数,将其传递给 ,\@task其定义方式是,它的参数是分隔;如果调用的是

\@task xyz:AB:cde:u\@nil

第一个参数是xyz,第二个参数是 ,AB第三个参数是cde:u。这里\@nil没有任何意义,它只是 的语法所要求的,\@task而 TeX 会将其丢弃。

\relax是 TeX 的一个原语,它的功能是“不做任何事”。测试

\if\relax\detokenize{#2}\relax

是确定参数是否#2为空的安全方法。如果为空,\detokenize{#2}则扩展为零,因此\if比较标记\relax\relax,它们确实相等,因此遵循“真”分支,该分支在第二个之后立即开始\relax,直到并且不包括\else。如果#2不为空,假设它是30\if\relax与哪些不同,因此遵循“假”分支,该分支在直到并且不包括3之后开始。[1]\else\fi

类似的构造\if\relax#2\relax并非在所有情况下都有效,因为“就 \if 而言,所有控制序列都是相等的” [2]。如果#2\relax(或任何其他控制序列,可能后面跟着其他标记),它将不起作用!因此,我们使用它,正如 Joseph 所解释的那样,将所有内容拆分成一个字符串。因此\detokenize,即使在奇怪的情况下,也会将标记与#2\relax\if\relax特点 \,它们是不同的。


[1] 这并非完全正确,但对于本描述的目的而言,这是一个近似的事实。

[2] TeX 按主题分类(第 13.2.1 节)

答案2

\detokenize原语将其所有输入转换为类别代码 12(“其他”)标记,但空格除外,空格仍保留为类别代码 10(“空格”)。它用于将标记转换为字符串。例如,如果我们有

\detokenize{\foo}

那么\foo就是一个控制词,IE一个标记,它被转换成 5 个字符串字符(\foo),所有这些都是除空格之外的“其他”字符,空格是“空格”。请注意此处末尾的额外空格:\detokenize在每个“控制字”后添加一个空格(见下文)。

我将一步一步地介绍你的例子。首先,\@nil在这里用作分隔符。的定义\@task意味着参数必须包含:,然后:再次包含,最后包含\@nil。这用于“整理”尴尬的输入

\task{stuff:more stuff}

将会变成

 \@task stuff:more stuff::\@nil

意思#1是 是stuff#2more stuff#3:。这样可以确保所有东西都“用完了”:这是常见的要求。


要查看\detokenize实际效果,请尝试以下操作

\documentclass{article}
\usepackage[T1]{fontenc}
\edef\test{\detokenize{\test}}
\show\test
\begin{document}
\detokenize{\test}
\end{document}

关于用 增加空格的更多\detokenize信息,实际上更一般地讲。每当 TeX 将可以作为一个或多个标记的内容写成“字符串”时,它总是在每个“控制字”(转义字符后跟一个或多个“字母”)后插入一个空格,以避免混淆。例如,使用

\catcode`\X=12 % 'Other'
\def\foo{\barX}
\meaning\foo

你得到

macro:-> \bar X

原文中没有空格,但告诉我们这\bar是控制序列,后面跟着X,而不是只打印\barX,这看起来是不同的东西。这是有道理的,因为 TeX 会跳过控制字后的空格,所以就 TeX 而言,这两个版本是等效的。

遵守了这种“插入空格”行为\detokenize,这意味着每个控制字后都会有一个空格。TeX 唯一不插入这些空格的地方是\string,它只能在单个标记上使用,因此在不可能“混淆”的地方使用。

相关内容