例如\exp_args:Nxo
可用但 不可用\exp_args:NxV
。我们可以安全地使用前者代替后者吗?
答案1
不,它们并不相同,即使在某些情况下它们确实会产生相同的结果。
\documentclass{article}
\ExplSyntaxOn
\tl_new:N \l_jl_test_tl
\int_new:N \l_jl_test_int
\tl_set:Nn \l_jl_test_tl { tokens }
\int_set:Nn \l_jl_test_int { 42 }
\exp_args_generate:n { xV }
\ExplSyntaxOff
\begin{document}
\ExplSyntaxOn
\exp_args:NxV \use_ii:nn { whatever } \l_jl_test_tl
\par
\exp_args:NxV \use_ii:nn { whatever } \l_jl_test_int
\par
\exp_args:Nxo \use_ii:nn { whatever } { \l_jl_test_tl }
\par
\exp_args:Nxo \use_ii:nn { whatever } { \l_jl_test_int }
\ExplSyntaxOff
\end{document}
你发现问题了吗?
您还会看到,如果某些\exp_args:N...
组合不是现成的,您可以非常简单地生成它。
请注意一个o
论点应该需要支撑,相反,V
参数则不需要。TeX 可能无论如何都会做“正确”的事情,但这一事实无关紧要。
另一方面,很多\exp_args:N...
当这种情况不止一次发生时,最好避免使用,实际上建议不要使用。如果您觉得有必要使用\exp_args:NxV
,那么很可能您想定义合适的函数变体。
答案2
问题不在于和是否o
等价V
,显然情况并非如此,问题在于是否可以用来模拟V
。o
答案是肯定的,正如文档interface3.pdf
(第 3 页)所建议的那样,但其中存在微妙之处。V
参数说明符获取变量的内容,但事情取决于变量。
我们可以对变量进行分类
- 类似变量的标记列表:tl、str、seq、clist、prop、fp
- 类似 int 的变量:int、dim、skip、muskip
- 夸克
- intarray、fparray、cctab
对于类别 1 和 3,\foo:V <variable>
替换为\foo:o { <variable> }
对于类别 2,\foo:V <variable>
替换为\foo:o { \<type>_use:N <variable> }
对于类别 4,变量不适合作为参数V
。
int、dim、skip、muskip 的演示
\MyTest:nn
如果两个参数作为标记列表相等,则打印 SUCCESS,否则打印 FAILURE。
% !TeX program = lualatex
\documentclass{article}
\begin{document}
\noindent
\ExplSyntaxOn
\cs_new:Nn \MyTest:nn {
\tl_if_eq:nnTF { #1 } { #2 } { SUCCESS } { FAILURE } \\
}
\cs_generate_variant:Nn \MyTest:nn { Vo }
\int_set:Nn \l_tmpa_int { 1234 }
\MyTest:Vo \l_tmpa_int { \int_use:N \l_tmpa_int }
\dim_set:Nn \l_tmpa_dim { 1234pt }
\MyTest:Vo \l_tmpa_dim { \dim_use:N \l_tmpa_dim }
\skip_set:Nn \l_tmpa_skip { 1234pt plus 1cm minus 2mm }
\MyTest:Vo \l_tmpa_skip { \skip_use:N \l_tmpa_skip }
\muskip_set:Nn \l_tmpa_muskip { 1234mu }
\MyTest:Vo \l_tmpa_muskip { \muskip_use:N \l_tmpa_muskip }
\end{document}
tl、str、seq、clist、prop、fp 和 quark 的演示
对于\MyTest:Nn
,#1 设置\My_var
为#2
并\MyTest:Vo
使用适当的参数调用。
% !TeX program = lualatex
\documentclass{article}
\begin{document}
\noindent
\ExplSyntaxOn
\cs_new:Nn \MyTest:nn {
\tl_if_eq:nnTF { #1 } { #2 } { SUCCESS } { FAILURE } \\
}
\cs_generate_variant:Nn \MyTest:nn { Vo }
\cs_new:Nn \MyTest:Nn {
#1 \My_var { #2 }
\MyTest:Vo \My_var { \My_var }
}
\MyTest:Nn \tl_set:Nn { \def\My#1{#1#1} }
\MyTest:Nn \str_set:Nn { \def\My#1{#1#1} }
\MyTest:Nn \seq_set_from_clist:Nn { \def, \My, #1, {#1#1} }
\MyTest:Nn \clist_set:Nn{ \def, \My, #1, {#1#1} }
\MyTest:Nn \prop_set_from_keyval:Nn {
\def = \My,
#1 = {#1#1},
}
\MyTest:Nn \fp_set:Nn { 3.14159 }
\quark_new:N \q_My
\MyTest:Vo \q_My { \q_My }
\end{document}
不太做作的例子
这说明了什么是可能的,但是不应该在生产代码中使用,因为它使用了不受支持的功能。
这里我们定义\foo:n
从其参数构建属性列表,假设它是属性列表变量的原始内容并打印出项目。然后我们生成“o”和“V”变体以最终测试\foo:o
和\foo:V
。
% !TeX program = lualatex
\documentclass{article}
\begin{document}
\noindent
\ExplSyntaxOn
\cs_new:Nn \foo:n {
\tl_set:Nn \l_tmpb_prop { #1 }
\prop_map_inline:Nn \l_tmpb_prop {
##1$\to$##2\\
}
}
\cs_generate_variant:Nn \foo:n { o, V }
\prop_set_from_keyval:Nn \l_tmpa_prop {
KEY1=VALUE1,
KEY2=VALUE2,
}
\foo:V \l_tmpa_prop
\prop_set_from_keyval:Nn \l_tmpa_prop {
key1=value1,
key2=value2,
}
\foo:o { \l_tmpa_prop }
\ExplSyntaxOff
\end{document}
它安全吗?
对于短时间使用来说,这是可以的,但对于部署代码来说,这绝对不行。如果 LaTeX 内部发生变化,这可能会在将来中断。