LaTeX3:如何在本地定义变量

LaTeX3:如何在本地定义变量

我正在尝试学习 LaTeX3 语法。我想到的一个问题是如何在组内定义具有局部作用域的变量(即 TeX 术语中没有参数的宏)。

在 TeX 中,\def'ed 宏是定义它的组的本地变量。如果\tl_new:Nn是 LaTeX3 中的对应项\def\...{...},我期望变量\world也是组的本地变量,但以下代码编译时没有错误:

\documentclass{article}
\usepackage{expl3}

\begin{document}

\ExplSyntaxOn
\group_begin:
  \tl_new:Nn\world{world!}
  %\def\world{world!}
\group_end:
\ExplSyntaxOff

hello \world
\end{document}

为什么\world在群外可见?

答案1

\tl_new:XXXX不像\def,而更像\newcommand:它声明了一个新的命令来保存内容。内容被填充,\tl_set并且存在局部和全局变体:例如。\tl_gset:Nn\tl_set:Nn

顺便说一句:你的例子对我来说不起作用,我明白

! Undefined control sequence.
l.10 \begin_group

miktex最近expl3在 2 天前进行了更新。

答案2

为了回答这里隐含的问题(“为什么会这样?”),所有命令\«variable»_new:N都会创建全局寄存器或宏。因此为了保持一致性, 也这样做\tl_new:Nn。我们还讨论了添加\«variable»_new_local:N(请参阅 etex.sty 了解 TeX 中本地寄存器的示例),但决定这样做的好处并不能抵消坏处:

为了:

  • 最好有本地寄存器(但不是必需的)

反对:

  • 语法和文档变得复杂,因为我们需要解释何时/为什么要使用它们。

我喜欢写作的想法

\group_begin:
  \int_new:N \l_track_loop_int
  ...
  « do stuff with \l_track_loop_int »
  ...
\group_end:

但最终大的问题是:

  • 本地宏的行为与本地寄存器不同,这会破坏tl数据类型和所有其他数据类型(如intdim等)之间的一致性。(并且我们不会为宏编写分配系统,因为效率会受到影响,而收益却很小。)

举例来说,如果\«var»_new_local:N分配器存在:

\group_begin:

  \tl_new_local:N \foo
  \tl_gset:Nn \foo {hello}

  \dim_new_local:N \baz
  \dim_gset:Nn \baz {1pt}

\group_end:

在这样的构造中,\foo在组之后仍然可用,而\baz不能。(请注意,全局设置局部变量是完全有效的。)这是一个足够重要的边缘情况(在我看来),可以最终决定反对这个想法。

因此,推荐的系统是正式声明您打算使用的所有变量(要么在包的开头集中在一起,要么在第一次使用时交叉使用)。但是,\tl_set:Nn如果需要,在组中使用以创建临时宏没有任何技术问题。

答案3

\tl_new:Nn扩展为\chk_if_free_cs:N#1\cs_gset_nopar:Npn#1{#2}\cs_gset_nopar:Npn\gdef。因此它给出了一个全局定义。

相关内容