如果你曾经尝试过阅读一些宏包或模板的源码,那么你一定见到过一大堆的带 @
符号的命令,是不是看得很头疼呢?按理来说呢,变量/函数的命令方式是为了让其变得更加易读,可 LaTeX
的这个 @命名法
似乎让其变得更加难读了.
其实呢更多的还是心理障碍,看到一大堆 @
总会让人感觉头疼,这和刚学习 LaTeX3
的时候看到那长长的命名规则一样,但是习惯之后就好了.
为什么要使用 @
参杂在命令名里面,这得先了解一下 catcode
,中文翻译为类别码 category code
. TeX 中的所有字符都分配有 catcode
,总共有 16 个 catcode
,如下表所示
Catcode | 含义 | 描述 |
---|---|---|
0 | Escape character | 默认是反斜杠 \ . 用于引入控制序列和其他特殊符号. |
1 | Begin group | 左花括号 { . 用于开始一个组. |
2 | End group | 右花括号 } . 用于结束一个组. |
3 | Math shift | 美元符号 $ . 用于开始和结束数学模式. |
4 | Align tab | & . 在表格和对齐环境中使用. |
5 | End of line | 换行符(例如 \n 或 \r ). 表示一行的结束. |
6 | Parameter | # . 用于宏参数的表示. |
7 | Superscript | ^ . 在数学模式中用于上标. |
8 | Subscript | _ . 在数学模式中用于下标. |
9 | Ignored character | 空格字符. 会被忽略,除非在某些特定环境下(如 \verb ). |
10 | Space | 空格字符. 被解释为空格,但可以用来分隔控制序列. |
11 | Letter | 字母字符. 用于构成控制序列的名称. |
12 | Other character | 其他字符. 可以直接使用,但没有特殊含义. |
13 | Active character | 活动字符. 通常是 ~ ,可以定义为宏. |
14 | Comment character | % . 用于注释,直到行结束. |
15 | Invalid character | 不合法字符. 通常是非 ASCII 字符,会引起错误. |
这里并不打算一一详细介绍这些 catcode
,只介绍 11 和 12
- 11(letter character), 代表的是所有拉丁字母, 即
A-Z
和a-z
- 12(other character), 代表的是其它字符, 例如
@
在 LaTeX 中,一个命令通常是由一个 catcode
为 0
的字符(通常为 \
)开始,然后紧跟着一堆 catcode
为 11
的字符(通常为拉丁字母 A-Za-z
)组成. 所以诸如 \foo123acd
, \bar@abc
这些都是不合法的.
在命令行使用
latexdef -s makeatletter
latexdef -s makeatother
分别得到
% latex.ltx, line 1693:
\DeclareRobustCommand\makeatletter{\catcode`\@11\relax}
% latex.ltx, line 1694:
\DeclareRobustCommand\makeatother{\catcode`\@12\relax}
可见 \makeatletter
实际上就是 \catcode\@ = 11
, 功能就是将 @
的 catcode
改为 11, 其实 makeatletter
就是 make @ letter
,当 @
的 catcode
改成 11 后,依照上面的规则,此时 @
就和普通的拉丁字母无异了,\bar@abc
便是合法的变量名了.
接下来看一些变量名, \easytoolsrangetolist
, \easytoolsgetlength
, \easytoolspaperwidth
, \easytoolsifshowframe
, 解释一些这些命令, \easytoolsrangetolist
其中 easytools
是模块名(通常是宏包或者模板名字), 用它作为前缀方便区分命令是哪个宏包/模板提供的, 也变相的为 LaTeX 提供了 “命名空间” 防止命令名重复, rangetolist
是变量/函数的名字. 但是一大串的字母堆叠在一起,分词的时候还是挺费劲的. 在其它语言中有驼峰命名和下划线命名等方法, \EasytoolsRangeToList
, \easytoolsRangeToList
, \esaytools_range_to_list
这些命名方案都要比 \easytoolsrangetolist
好得多.
再接下来需要聊一聊私有变量/函数的问题了,当你在写一个宏包或者模板的时候,你会定义很多变量/函数,但是实际给用户用到的也就那么几个,其它命令/函数称为私有命令/函数,这部分使开发者不希望用户直接使用和修改它们的,这时候便可以通过改变 @
的 catcode
为 11, 使得可以在命令中加入 @
而变成 \easytools@range@to@list
.
由于在普通的 .tex
文件中,@
的 catcode
为 12, 所以无法直接使用带 @
的命令,这就能够避免用户修改和使用开发者定义的私有命令/函数,然而在 .sty
和 .cls
文件中,@
的 catcode
已经被修改成 11 了,可以直接只用它作为命令名的一部分.
如果非要在 .tex
文件中使用和修改私有变量/函数呢,这就需要使用 \makeatletter
将 @
的 catcode
改成 11, 最后再使用 \makeatother
将 @
的 catcode
恢复回来. 只是在使用它们的时候希望你清楚你在做什么,否则不建议使用它们.
\makeatletter % changes the catcode of @ to 11
<your changes here>
\makeatother % changes the catcode of @ back to 12
总结一下,\makeatletter
和 \makeatother
是用来修改和恢复 @
的 catcode
的,使用 @
作为命令名的组成部分主要有两个方面的作用
- 断词分割符
- 私有变量/函数
- ...