关于 `\cs_new:...` 及其 TeX 亲属的问题,涉及 global、local、long、nopar、protected、expandable 和命名

关于 `\cs_new:...` 及其 TeX 亲属的问题,涉及 global、local、long、nopar、protected、expandable 和命名

这个问题有两个方面。不幸的是,一方面是固执己见,即需要关闭投票,所以我把这部分放在最后,希望没人注意到……另一方面(首先)是严肃的 interface3 问题,我希望看到答案。

interface3.pdf 文档承诺,它将在 TeXhacker 注释中为每个命令写出它们接近哪个 latex2 命令或 TeX 基元。但它没有在任何地方包含\gdef\global\def

  1. 确实是\cs_gset:Npn\long\global\def
  2. \cs_set_protected:Npn好像\protected\long\def

据我所知,latex3 还旨在将“TeX 编程语言”转变为更合理的环境,即更难意外产生错误的环境。实现此目的的一种方法是使用显式而不是隐式,尤其是在危险的情况下。考虑到这一点:

  1. \cs_new:Npn[存在的] 是否更有可能是[\cs_gnew:Npn我的发明],即全球性的?
  2. \cs_set:Npn[存在的] 是否类似于[\cs_lset:Npn我的发明],即本地的?
  3. [\cs_lnew:Npn我的发明]被认为没有用,所以被放弃了,对吗?
  4. 不合格函数(无 l、无 g)有时表示局部,有时表示全局(set 与 new),这合理吗?→ 令人困惑 → 错误

  5. \long现在是隐式的,因为这是大多数程序员所期望的,尤其是使用 latex3 语法。对吗?

  6. 现在调用了 Non-long ..._nopar:...。这是意料之外的,所以它有一个明确的标签,与 TeX 最初的标签相反。对吗?
  7. 为什么\protected不能基于同样的理由而隐含?即\cs_new_protected:Npn[存在的]应该被称为\cs_gnew:Npn[我的发明],而\cs_gnew_unprotected:Npn[我的发明]可以是当前的\cs_new:Npn[存在的]。

答案1

我看到Marcel 已经报道过 (1) 和 (2):我会尽力解决其他问题。

在 中,尽可能将“变量”和“函数”视为相同expl3。但是,有些地方会稍微棘手一些。其中一个地方是,\g_...在每个函数名称中都使用 会很麻烦:与变量不同,很少有函数被重复设置。因此,保存堆栈累积等风险很低。

所有“新”函数在创建其参数时都以全局方式起作用;对于变量,它们也在全局范围内初始化。对于函数,没有“初始”值,因此\cs_new:Npn和类似的在全局范围内设置:相当于\global\long\def。在指示范围的地方,这总是使用g......名称,所以没有lset,它只是“设置”。

创建局部函数/变量的用法以前也出现过,通常是在变量的上下文中。有人尝试过,但似乎与 TeX 的分组模型不太相符,所以没有保留。这又用了“new”而不是“gnew”:变量是总是声明,这是总是全球的。

至于“new”是否是全局的并且不需要“gnew”,我留给其他人去判断:我觉得有一套明确的“始终全局”的操作是可以的。

除非在代码级别另有标记,否则所有内容都是“长”。通常,Knuth 的\long标记在文档中很有用,但在代码中却有问题。标记的现状是由于语言的发展:事物最初更接近 TeX 命名(例如,\def_new:Npn而不是\cs_new_nopar:Npn)。由于“长”状态是默认状态,因此更容易使“nopar”标记显式化。

受保护状态的平衡更为复杂:无论采取哪种方式,都会有大量的“其他情况”。同时,语言开发早在需要 e-TeX 之前就开始了。因此,在最初的想法形成之后,才添加了受保护状态。团队已经讨论过这个问题(以及函数名称不表示扩展行为的事实),但在这个阶段,改变这里实在是太晚了。

答案2

  1. 确实是\cs_gset:Npn\long\global\def

\cs_gset:Npn定义为\tex_long:D \tex_gdef:D,因此它与 完全相同\long\gdef

  1. \cs_set_protected:Npn好像\protected\long\def

\cs_set_protected:Npn定义为\tex_protected:D \tex_long:D \tex_def:D,所以它与完全相同\protected\long\def

(请参阅texdoc source3第 5.3 节“定义函数”以供参考)

答案3

每个<module>_new<...>功能全球定义一个函数或变量,将其设置为合理的值。如果你这样做

  • \cs_new:Npn #1 \siemer_foo:n { whatever #1 },该函数是全局定义的,其动作将按照定义进行。
  • \tl_new:N \l_siemer_foo_tl,token列表变量全局定义,并初始化为空。
  • \int_new:N \g_siemer_foo_int,整型变量全局定义,初始化为0。

\g_...对于变量来说和有什么区别\l_...?前者类型应始终全局设置,后者局部设置。如果您这样做,TeX 不会引发错误\int_set:Nn \g_siemer_foo_int { 42 },但西班牙宗教裁判所可能会开始追捕您,expl3因为概念上是错误的。实际上,如果使用以下选项加载,则会引发错误check-declarations

! LaTeX3 Error: Inconsistent local/global assignment

For immediate help type H <return>.
 ...                                              

l.8 \int_set:Nn \g_siemer_foo_int { 42 }

这种检查计算量很大,因此只应在编写和测试代码时使用,而不是在标准文档上运行 LaTeX 时使用。

结果是没有“局部变量”的概念,即变量只能在本地使用。由于 TeX 没有“命名空间”的概念,因此最好使用描述性变量名,以确保它们的用法。与仅在本地声明变量\<module>_gnew<...>相比,不提供\<module>_new<...>变量名是一个明智的选择。

然而,具有局部函数,这些函数仅在其定义的组中可用。这就是函数系列的用途\cs_set

\cs_new那么和之间有什么区别呢\cs_gset? 一个很大的区别:前者函数系列检查要定义的函数是否不存在;后者只是在没有警告的情况下覆盖定义。

因此, 是不正确的\cs_new:Npn\long\global\def它是“检查函数是否存在,如果存在则抛出错误,否则执行 ” \long\global\def。另一方面,\cs_gset:Npn\long\global\def

函数不必如此\protected:如果是,那么其中一些函数将停止工作。举一个简单的例子,\int_eval:n 一定不\protected,因为它的工作是在扩展上下文中提供十进制表示的整数。

相关内容