背景
在 LaTeX3 中,我正在编写一些宏来存储和读取变量的内容,就像\tl_set:Nn
does 一样。因此,我使用类型生成变体N
,这会导致警告。警告建议改用,V
这对阅读宏\tobiw_use_thing
,但感觉不对写作宏\tobiw_save_thing
。手册上说(我重点标出):
V 和 v 说明符用于得到变量的内容[…]
平均能量损失
\documentclass{article}
\usepackage{xparse}
\ExplSyntaxOn
\cs_new:Nn \tobiw_save_thing:nn {
\tl_set:Nn #1 { #2 }
}
\cs_generate_variant:Nn \tobiw_save_thing:nn { Nn }
\cs_new:Nn \tobiw_use_thing:n {
\tl_use:N #1
}
\cs_generate_variant:Nn \tobiw_use_thing:n { N }
\NewDocumentCommand{\saveanduse}{ m }{
\tobiw_save_thing:Nn \l_tmpa_tl { #1 }
\fbox { \tobiw_use_thing:N \l_tmpa_tl }
}
\ExplSyntaxOff
\begin{document}
Test
\saveanduse{Tokens}
\end{document}
问题
那么,创建此类宏的最佳方法是什么?这里应该使用哪些参数类型?
答案1
你一定不在这里使用变体。
当基本函数的签名仅由N
或n
说明符组成(或在包容意义上,要清楚),并且在执行操作之前需要某种类型的参数扩展时,就需要变体:
V
是 的变体n
,其中变体函数将接收单个标记(应该是合适变量的名称)并且基本函数将接收n
该值作为其参数。f
和x
是 的变体n
,其中括号中的内容将被f
- 或x
-扩展。o
是 的变体n
,其中括号中的内容将“扩展一次”,即列表中的第一个标记将扩展一次。c
是 的变体N
,其中括号中的内容将被转换为单个标记作为参数N
。
您正在定义两个基本函数,并且都期望单个标记作为它们的第一个(或唯一)参数:这要求一个类型的参数N
。
\documentclass{article}
\usepackage{xparse}
\ExplSyntaxOn
\cs_new_protected:Nn \tobiw_save_thing:Nn
{
\tl_set:Nn #1 { #2 }
}
\cs_new:Nn \tobiw_use_thing:N
{
\tl_use:N #1
}
\NewDocumentCommand{\saveanduse}{ m }
{
\tobiw_save_thing:Nn \l_tmpa_tl { #1 }
\fbox { \tobiw_use_thing:N \l_tmpa_tl }
}
\ExplSyntaxOff
\begin{document}
Test
\saveanduse{Tokens}
\end{document}
请注意,第一个函数应使用 来定义_protected
,因为它套一些变量。
定义设施的函数\cs_new_...
或\cs_set_...
具有基本签名:Nn
或:Npn
。定义函数的签名应仅由N
或n
(包含意义)的字符串组成;w
仅在情况下才允许:Npn
。
例如,你有\tobiw_use_thing:N
,但你可能想要
\cs_new:Nn \tobiw_use_thing:n
{
Do something with #1
}
\cs_generate_variant:Nn \tobiw_use_thing:n { V }
允许如下调用
\tobiw_use_thing:n {whatever}
或者
\tobiw_use_thing:V \l_tmpa_tl
但最终这取决于你的功能应该做什么。
答案2
这里不需要任何变体,只需定义N
带有类型参数的函数即可。如果您主要关心的是允许分组输入(如 csname),c
则随后生成一个变体。
n
您的函数使用代表一组标记的说明符。您可以将它们(作为变体)转换为V
类型参数,因为这样可以保留获取一组标记的想法。另一方面,您有一对c
和N
,前者接受一组标记(但从中形成一个控制字),后者接受一个标记,即一个控制字。
在设计函数时,你应该考虑到参数的目的。如果你希望将控制序列作为参数,请使用N
或之一c
。如果你希望获得某个值,请使用n
、o
、x
、f
或。V
v
\documentclass{article}
\usepackage{xparse}
\ExplSyntaxOn
\cs_new:Nn \tobiw_save_thing:Nn {
\tl_set:Nn #1 { #2 }
}
\cs_generate_variant:Nn \tobiw_save_thing:Nn { cn }
\cs_new:Nn \tobiw_use_thing:N {
\tl_use:N #1
}
\cs_generate_variant:Nn \tobiw_use_thing:N { c }
\NewDocumentCommand{\saveanduse}{ m }{
\tobiw_save_thing:Nn \l_tmpa_tl { #1 }
\fbox { \tobiw_use_thing:N \l_tmpa_tl }
}
\ExplSyntaxOff
\begin{document}
Test
\saveanduse{Tokens}
\end{document}