expl3: 实践中`:V`和`:x`有什么区别?

expl3: 实践中`:V`和`:x`有什么区别?

当命令\...:n需要接收参数的值时,可以使用其:V变体。但在我了解之前:V,我一直使用:x来使参数完全展开,这通常会导致值。在实践中我不太清楚应该使用哪一个,我一直在从这两个中随机选择。

在以下示例中,它们产生相同的结果。但如果没有\number,则只有:V版本有效。这是否意味着:V版本通常更适合此提议?

\documentclass{article}

\ExplSyntaxOn

\begin{document}

\cs_new:Nn \mymodule_mytest:n { #1 }

\exp_args:NV \mymodule_mytest:n { \number \year }

\exp_args:Nx \mymodule_mytest:n { \number \year }

\end{document}

答案1

-type参数V应该是一个单独的标记,即变量的名称。在 TeX 级别,这些可以实现为宏或寄存器 - 要访问后者,在 TeX 级别需要\the\number(在适当的情况下)。所有这些都包含在一些巧妙的代码中,这样V-type 参数就可以“正常工作”

\tl_set:NV \l_tmpa_tl \l_tmpa_int

例如将(宏)设置为(寄存器)tl的值。int

扩展为值本身是可扩展的,并且只会对标记列表执行一级扩展。因此

\tl_set:Nn \l_tmpa_tl { bong }
\tl_set:Nn \l_tmpb_tl { \l_tmpa_tl }
\tl_gset:Nx \g_tmpa_tl { \exp_not:V \l_tmpb_tl }

将导致\g_tmpa_tl包含\l_tmpa_tl,而不是bong

相反,x-类型扩展是不可扩展,采取平衡文本参数并彻底扩展其中的所有内容。这意味着x-type 参数中的变量需要适当的访问器。

\tl_set:Nx \l_tmpa_tl { \int_use:N \l_tmpa_int }

并且如果应用于,我们将获得最终的、不可扩展的标记tl,因此

\tl_set:Nn \l_tmpa_tl { bong }
\tl_set:Nn \l_tmpb_tl { \l_tmpa_tl }
\tl_gset:Nx \g_tmpa_tl { \l_tmpb_tl }

表示\g_tmpa_tl包含bong

答案2

2023 年 1 月添加

问题是关于x-expansion 的,但现在e-expansion 更方便。只需xe下面的替换即可。

回答

函数签名(冒号后的部分)中字母的约定是大写字母表示单个标记参数(无括号),小写字母表示带括号的参数。例外:TF用于条件语句中,表示带括号的参数;它们始终位于用 定义的函数名称的最后\prg_new_(protected_)conditional:Nnn

当然,expl3不能改变 TeX 的语法规则,因此在不需要括号的参数周围添加括号会导致简单地删除它们;但是,请利用这个事实。如果

  • 总是避免使用括号NV输入参数;
  • 总是使用括号括起所有其他参数类型。

V那么,和之间有什么区别吗x?有区别,就像比较鱼和树一样。原因如下:

  1. 论据V单身的令牌;
  2. 一个x参数可以由多个标记(甚至零个)组成;
  3. 参数必须是类型为、或的任何与寄存器相对应的类型V的变量,即、或。tlcliststrintdimskipmuskip
  4. 争论x可以是任何事情;
  5. 参数V将返回变量的内容作为括号n参数;
  6. 一个x论点是一个支撑论点。

\number除了不应该在代码中使用之外expl3,你的尝试

\exp_args:NV \mymodule_mytest:n { \number \year }

纯粹是偶然产生的2022。如果你遵循上面关于括号的约定,你永远不会尝试它:这就像尝试\mbox\number\year显然行不通。\mbox\bgroup xyz\egroup或者似乎工作,但实际上却不能,并且纯属偶然没有产生任何错误消息。

假设您想要将\c_sys_year_int(又名\year)的值传递\my_command:n给它,进而提取第一个数字;您将这样做

\cs_new:Nn \jinwen_extract_msd:n
 {
  \tl_head:n { #1 }
 }

msd代表“最高有效位”)。然后,您可以通过三种方式获得结果:

\exp_args:NV \jinwen_extract_msd:n \c_sys_year_int
\exp_args:Ne \jinwen_extract_msd:n { \int_use:N \c_sys_year_int }
\exp_args:Nx \jinwen_extract_msd:n { \int_use:N \c_sys_year_int }

最后一个是最不推荐的,因为它不是可扩展。中间的那个和上面的一样可扩展,但是很复杂,效率很低。

但是,一般来说,你不应该使用\exp_args:NV。除非是一次性应用程序,否则最好定义一个变体:

\cs_new:Nn \jinwen_extract_msd:n
 {
  \tl_head:n { #1 }
 }
\cs_generate_variant:Nn \jinwen_extract_msd:n { V }

你可以直接调用

\jinwen_extract_msd:V \c_sys_year_int

这比上面的三个标记构造更清晰,不是吗?

相关内容