在我对这个问题的回答中\makeatletter 和 \makeatother 起什么作用?我显然写道:
这些命令不应在文件本身内使用
.sty
,.cls
因为它们可能与加载包和类文件时发生的 catcode 更改相冲突。
事实上,这一行是 Will Robertson 添加的。所以我很好奇:有人能举一个具体的例子来说明在包或类的开头和结尾使用\makeatletter
and会如何影响另一个包吗?\makeatother
我并不是在谈论如果遗漏其中一个会发生什么,正如这里所讨论的:
答案1
首先,在或文件\makeatletter
中是不必要的,因为默认的 catcode 机制包含它;这大概是为了鼓励包编写者使用-laden 名称来隐藏他们的宏。出于这个原因,我认为使用.sty
.cls
@
这命令在包文件中是无害的。
然而,使用一对命令在一起是有害的,因为与文档不同,你不是想要返回到@ = other
包内的设置。这些是文档命令,标准顺序\makeatletter \makeatother
假定这\makeatother
实际上是撤消先前的更改,而在包中,这是进行更改的命令。
编辑:以下是一个更明智的答案。根据source2e.pdf
,使用以下方案来加载包和类:
- 首先,收集选项等。
- 然后是当前文件的名称(即
mypackage.sty
),以及 catcode@
,都保存在堆栈中。 - 然后
\makeatletter
运行,如果合适,则加载请求的文件。 - 随后,弹出堆栈并恢复预包加载状态。
换句话说,以下无知代码毫无效果:
\documentclass{article}
\usepackage{bad}
\begin{document}
\end{document}
坏.sty:
\makeatletter
\makeatother
\RequirePackage{unsuspecting}
然而,很有可能一个包确实不是使用\RequirePackage
,但只是\input
。在这种情况下,catcode 是不是受保护,事实上,可能会出现错误,您可以通过以下方式自行检查bad.sty
,例如:
\makeatletter
\makeatother
\input{pgfkeys.sty}
如果这看起来是人为的,请看一下pgfkeys.sty
它本身:它\input
是pgfkeys.code.tex
,而该文件又\input
是pgfkeysfiltered.code.tex
。据推测,作者觉得自己在自己的软件包中是安全的,但没有想到其他人也可能绕过软件包加载保护机制!
答案2
在 LaTeX2.09 中,这个问题更加严重,因为 LaTeX 刚刚执行\makeatletter
一次在处理所有.sty
文件之前(LaTeX2.09 没有给出.cls
/.sty
区分)。因此,这是一个常见问题,几乎是一个常见问题,即发布的软件包\makeatother
在文件末尾执行,它们独立工作,但会破坏任何后续的“样式文件”(又名软件包)。
因此,2e 所做的第一件事就是在加载每个包时重置 catcode @
,维护一个堆栈,以便在包结束时将 catcode 恢复到之前的状态。因此通过设计很难找到\makeatother
包末尾的流氓程序造成危害的例子。
话虽如此,但最好不要跌倒,而不是依赖安全网。
答案3
只要您意识到不要在自己的包中做坏事(例如 Ryan Reich 的例子),您似乎在 LaTeX 提供的范围内是安全的。
但危险仍然潜伏在角落。
如果我说
\usepackage{afterpackage}
\AfterPackage{foo}{\input{bar}}
\usepackage{foo}
和里面foo.sty
\makeatother
和里面bar.tex
\protected@edef\baz{quux}
然后我收到一个错误,因为@
不是一个字母(如果没有就不会发生这种情况\makeatother
)。
(这个答案的重点当然是(毫无戒心的)使用者\AfterPackage
不一定与软件包作者相同)