当命令\...: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 更方便。只需x
用e
下面的替换即可。
回答
函数签名(冒号后的部分)中字母的约定是大写字母表示单个标记参数(无括号),小写字母表示带括号的参数。例外:T
和F
用于条件语句中,表示带括号的参数;它们始终位于用 定义的函数名称的最后\prg_new_(protected_)conditional:Nnn
。
当然,expl3
不能改变 TeX 的语法规则,因此在不需要括号的参数周围添加括号会导致简单地删除它们;但是,请不利用这个事实。如果
- 你总是避免使用括号
N
或V
输入参数; - 你总是使用括号括起所有其他参数类型。
V
那么,和之间有什么区别吗x
?有区别,就像比较鱼和树一样。原因如下:
- 论据
V
是单身的令牌; - 一个
x
参数可以由多个标记(甚至零个)组成; - 参数必须是类型为、或的任何与寄存器相对应的类型
V
的变量,即、或。tl
clist
str
int
dim
skip
muskip
- 争论
x
可以是任何事情; - 参数
V
将返回变量的内容作为括号n
参数; - 一个
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
这比上面的三个标记构造更清晰,不是吗?