LaTeX3 函数接口

LaTeX3 函数接口

我最近发布了一个问题,关于如何用纯 TeX 编写宏,该宏将修改用户指定列表中的元素。我随口提到我不喜欢 TeX 的界面,所以有人让我使用 LaTeX3,正如手册所承诺的那样,它应该更像一种现代编程语言。我刚刚开始使用 TeX 编程,因此试图理解手册是一场艰苦的战斗。我猜是因为手册是为经验丰富的 TeX 用户编写的;但是,对于刚开始使用 LaTeX3/TeX 的人来说,似乎没有其他选择,所以我别无选择,只能使用我已有的。这就是我发布此文的原因。手册令人困惑,我想通过问您一些关于语法的简单问题来消除一些困惑。

我应该提一下,告诉我有关 LaTeX3 的人还为我提供了一个使用其界面的原始帖子的解决方案。我能够将此解决方案与手册结合使用,开始找出有关 LaTeX3 语法的一些基本事实。我将谈论我设法弄清楚的内容,但公平地说,其中一些是基于我自己的推论 - 在 stackexchange 用户提供的示例的帮助下得出的 - 而不是手册中的明确说明,所以可能会有错误。我想让你知道,当我有时使用自己的术语时,我并没有混淆问题。只是很难以结构化的方式谈论你不完全理解的主题。

另外,由于篇幅较长,我将这篇文章作为单独的帖子而非评论来写。提前致谢。

--------------------------------------------------------------------------------------------------------------------------

函数定义

我目前弄清楚了什么

除其他方法外,还定义了一个新函数,代码如下:

\cs_new_<restrictions>:Npn <function name> <function parameters> {<replacement code>}

\cs_new_<restrictions>一个 LaTeX 命令,Npn 用于告诉接口的“解析器”在\cs_new_<restrictions>: Npn代码部分之后应该期待什么,在本例中,是一个单个标记控制字,即<function name>,一个或多个参数,即<function parameters>,以及一个标记列表,即{<code>},它替换了函数。

因此,如果我想定义一个接受 4 个参数的新函数,我可以使用以下代码

\cs_new_<restrictions>:Npn \myfunction #1 #2 #3 #4 {<code>}

类似地,具有 2 个参数的函数的代码可能看起来像这样

\cs_new_<restrictions>:Npn \myfunction #1 #2 {<code>}

当然,我假设 - 如果我错了请纠正我 - 空格不是必需的,因为解析器已经被告知如何在“元签名”的帮助下将“元”参数(,,<function name>)彼此区分开来<parameters>{<code>}氮氧化物

现在,如果我想去掉 #,我可以使用以下通用命令

\cs_new_<restrictions>:Nn <function name>:<function signature> {<code>}

类似的交易,除了现在解析器期望<function signature>之后出现像 Nn、NnN、TnN 或其他东西<function name>

再次,具有 4 个参数的函数可能如下所示

\cs_new_<restrictions>:Nn \myfunction:NNNN {<code>}

还有一个带有 2 个参数的

\cs_new_<restrictions>:Nn \myfunction:NN {<code>}

还有其他命令l3基础用于创建函数的库,但它们的总体结构似乎基本相同。唯一的区别在于它们的功能。例如,使用\cs_set...而不是\cs_new...会使函数成为本地函数而不是全局函数。我可能会写一篇后续文章,询问有关 e-type 和 x-type 扩展的更多详细信息,但目前我认为最好还是坚持大局。

不管怎样,到目前为止是这样吗?

好的,继续。

变量定义

我目前弄清楚了什么

LaTeX3 中有相当多的数据类型,但主要的有代币列表字符串整数序列, 和逗号分隔列表它们各自使用自己的缩写,但一般来说,定义新变量时,需要声明类型,并在其后跟上关键字,例如新的或者常量取决于您是否初始化变量。

例如,如果我想声明但不初始化一个代币列表变量我使用的代码:

\tl_new:N \mytokenList

然后在某个地方,我可以\mytokenList使用以下代码存储一个令牌列表:

\tl_set:Nn \mytokenList {<tokens>}

但是,如果我从一开始就知道我想在变量中存储什么数据,我可以使用此命令(不适用于序列或者整数

\tl_const:Nn \mytokenList {<tokens>}

另外:我注意到,甚至变量都有“函数签名”。这可能使定义解析机制变得更容易。

在我必须指定我所引用的数据类型之前,这大概就是我能做到的最通用的了,因为每个数据类型都有自己相关的操作。

--------------------------------------------------------------------------------------------------------------------------

这就是我目前所拥有的。我很感激任何反馈。这些东西并不容易自学!特别是对 TeX 了解甚少的人,所以如果你们中的一些人看到这个并认为“很明显”,我深表歉意。无论如何,再次感谢。

答案1

定义函数主要有两种方式:

\cs_new<restrictions>:Npn

\cs_new<restrictions>:Nn

其中 可以是_protected_nopar_protected_nopar

两种方法都检查N后面的参数(即单个标记)是否是当前未定义的控制序列(或活动字符),并且全球定义控制序列。

有什么区别?第一个系列要求,在要定义的控制序列之后,在{函数的界定“替换文本”之前有一个“参数文本”。

“参数文本”可以是任何标记序列,包括#1#2等等,直到#9。但是,为了充分领会这种自由的威力,您需要熟悉 TeXbook 第 20 章和“分隔参数”的概念。

不过,我们还是简单点吧。以下两段代码完全等价:

\cs_new:Npn \harry_foo:nn #1 #2 { -#1-#2- }
\cs_new:Nn \harry_foo:nn { -#1-#2- }

因为后者会#1#2根据要定义的函数的签名自动提供参数文本,在本例中是:nn

签名应该由nN字符序列(可能为空)组成。

请注意,当处于活动状态时,空格将被忽略\ExplSyntaxOn,因此

\cs_new:Npn \harry_foo:nn #1 #2 { -#1-#2- }
\cs_new:Npn \harry_foo:nn #1#2 { -#1-#2- }
\cs_new:Npn \harry_foo:nn #1#2{ -#1-#2- }

都是等效的。即使在 之后也可以有一个空格#,但我不建议这样做。

TeX 的语法规则规定,当它需要一个“参数文本”时(基本上,在执行\def或类似的分配时,并存储了要定义的宏的名称之后)一切直到第一个{都是参数文本的一部分。没有办法预见参数文本是什么,因此特殊的参数p说明符只表示“直到的一切{”。

#1只能自动生成诸如等简单的参数文本#1#2,这是在使用第二个系列时完成的\cs_new<restrictions>:Nn

你错在哪里?假设你可以T在签名中使用它作为说明符。参数说明符T或在执行F时添加。\prg_new_conditional<restrictions>:Nnn

另外,您对参数文本的分析是错误的,如前所示。

那么\cs_set<restrictions>:Npn和 呢:Nn? 上面的所有内容都适用,不同之处在于,不会检查要定义的函数是否已定义,并且其含义将被默默覆盖,但声明的范围与当前组一致。 通常,\cs_set...用于需要适应上下文的临时函数,因此它们的含义不是固定的。


变量的命名约定建议其名称以lg或开头c。实际上,代码中使用的变量expl3应符合惯例;可以使用“正常”名称,例如要在文档中使用的\myTokenList类型变量tl(也可能是)。clist

以 开头的变量l应始终在本地起作用(\tl_set:Nn比如说),而以 开头的变量g应始终在全局起作用(\tl_gset:Nn比如说)。

以 开头的变量c常量并且应该绝不在被赋予值之后才采取行动,但仅仅是被使用。

可以使用以下方式定义常量

\tl_const:Nn \c_harry_foo_tl {<tokens>}
\str_const:Nn \c_harry_foo_str {<tokens>}
\clist_const:Nn \c_harry_foo_clist {<comma list>}
\seq_const_from_clist:Nn \c_harry_foo_seq {<comma list>}
\prop_const_from_keyval:Nn \c_harry_foo_prop {<key-value list>}
\int_const:Nn \c_harry_foo_int {<integer expression>}
\fp_const:Nn \c_harry_foo_int {<fp expression>}
\bool_const:Nn \c_harry_foo_bool {<boolean expression>}
\dim_const:Nn \c_harry_foo_dim {<dimen expression>}
\skip_const:Nn \c_harry_foo_dim {<skip expression>}
\muskip_const:Nn \c_harry_foo_dim {<muskip expression>}
\intarray_const_from_clist:Nn \c_harry_foo_intarray {<comma list>}
\regex_const:Nn \c_harry_foo_regex {<regex>}
\cc_tab_const:Nn \c_harry_foo_cctab {<code>}

相关内容