我有一个非常简单的问题。当我这样做时:
\catcode`\@=0
\catcode`\\=11
@mycommand{a}
@catcode`@\=0
\catcode`\@=11
它运行完美,调用\mycommand
正确。然而,当我尝试\mycommand
用类似的技巧定义时:
\newcommand\mycommand[1]{
\catcode`\@=0
\catcode`\\=11
@textbf{Hello #1}
@catcode`@\=0
\catcode`\@=11
}
编译停止并给出*
提示。如果我输入Ctrl+ D,它会终止而不产生任何输出。事实上,更改命令中的 catcode 似乎没有任何效果,因为下面的代码运行正常(而据我所知,它不应该这样):
\newcommand\mycommand[1]{
\catcode`\@=0
\catcode`\\=11
\textbf{Hello #1}
}
谁能向我解释一下发生了什么事?
答案1
当你说
\newcommand\mycommand[1]{
\catcode`\@=0
\catcode`\\=11
@textbf{Hello #1}
@catcode`@\=0
\catcode`\@=11
}
TeX 将以下标记存储为替换文本\mycommand
(• 项目符号分隔标记并使用空格以提高可读性,<sp>
表示空格标记):
<sp> • \catcode • ` • \@ • = • 0 • <sp> •
\catcode • ` • \\ • = • 1 • 1 • <sp> •
@ • * t • e • x • t • b • f • { • H • e • l • l • o • <sp> • #1 • } •
@ • c • a • t • c • o • d • e • ` • @ • \= • 0 • <sp> •
\catcode • ` • \@ • = • 1 • 1 • <sp>
在哪里
@
,,,`
并且类别代码为120
,1
=
{
并}
分别具有类别代码 1 和 2,<sp>
类别代码为 10,- 这些字母的类别代码为 11。
类别代码为冻结一旦它们进入 TeX 的嘴里。当宏\mycommand{Worlds}
展开时,TeX 将更改@
从那时起它将吸收的所有内容的类别代码(尊重组),但这不能以任何方式改变已经标记的内容,例如标记序列
@ • * t • e • x • t • b • f
已存储。
将会打印出精确的内容
@textbfHello World @catcode'@0
(0 上会有一个横线)并且 TeX 不会有任何类别代码为 0 的字符,这意味着它无法识别命令。
我将用 Plain TeX 来做一个例子,它更容易打印,但本质上是等效的。我只会\csname bye\endcsname
在游戏结束时添加以下内容:
\def\mycommand#1{
\catcode`\@=0
\catcode`\\=11
@textbf{Hello #1}
@catcode`@\=0
\catcode`\@=11
\csname bye\endcsname
}
\mycommand{World}
请记住,当 TeX 执行 时\def
,它会完全禁用宏扩展和它吸收的宏名称、参数文本和替换文本的标记的命令执行。它只会扩展替换文本中的标记,但在执行 时不会再次执行它们\edef
。