专栏名称: LaTeX工作室
欢迎光临分享与学习LaTeX的王国
目录
相关文章推荐
最爱大北京  ·  2月10日 | 京城事儿全知道 ·  2 天前  
北京交通广播  ·  北京两天62起火警!消防紧急提醒 ·  3 天前  
北京交通广播  ·  北京两天62起火警!消防紧急提醒 ·  3 天前  
气象北京  ·  气象科普研学寒假班招生啦! ·  3 天前  
北京本地宝  ·  北京2025年5个重大地标! ·  6 天前  
51好读  ›  专栏  ›  LaTeX工作室

LaTeX 中的 \makeatletter 和 \makeatother

LaTeX工作室  · 公众号  ·  · 2024-06-04 22:10

正文

如果你曾经尝试过阅读一些宏包或模板的源码,那么你一定见到过一大堆的带 @ 符号的命令,是不是看得很头疼呢?按理来说呢,变量/函数的 命令方式 是为了让其变得更加易读,可 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 .







请到「今天看啥」查看全文