我发表了自己对所发生事情的解释,希望如果我错了,有人能够指出并解释原因。
xparse
的问题\IfNoValue
并不n
像@ScottH 所暗示的那样取决于传递类型参数。问题似乎隐藏在 的定义深处\IfNoValue
。
它的优点在于\IfNoValue
,它被设计成可以记录参数是否为空,而无需最终用户能够偶然通过参数传递将被解释为空参数的东西。也就是说,\IfNoValue{-NoValue-}
应该注册 false。这是通过一些花哨的小写值的临时分配和使用诡异的(w
)类型参数。
下面的例子说明了正在发生的事情:(在大多数情况下,我xparse
在定义命令时都会遵循的引导,以便尽可能地反映我之前的问题。)
\documentclass{article}
\usepackage{xparse}
\ExplSyntaxOn
\cs_new:Npn \ae_experiment:w #1 DELIMITER { #1 }
\cs_new:Npn \ae_testing_weird:n #1 {
\str_if_eq:onTF
{ \ae_experiment:w #1 DELIMITER }
{ Andrew }
{ \emph{moi} }
{ \textbf{not}~me }
}
\cs_new:Npn \ae_testing_ntype:n #1 {
\str_if_eq:onTF
{ #1 }
{ Andrew }
{ \emph{moi} }
{ \textbf{not}~me }
}
\cs_new_eq:NN \testingWeird \ae_testing_weird:n
\cs_new_eq:NN \testingNtype \ae_testing_ntype:n
\NewDocumentCommand{\bypassWeird}{m}
{
\tl_set:Nn \l_ae_bypass_tl {#1}
\exp_args:NV \testingWeird \l_ae_bypass_tl
}
\NewDocumentCommand{\Andrew}{}{Andrew}
\ExplSyntaxOff
\pagestyle{empty}
\begin{document}
\begin{tabular}{lccc}
Func. Call & \verb=Andrew= & vs. & \verb=\Andrew= \\\hline
\verb=Weird= & \testingWeird{Andrew} & & \testingWeird{\Andrew} \\
\verb=Ntype= & \testingNtype{Andrew} & & \testingNtype{\Andrew} \\
\verb=bypassed= & \bypassWeird{Andrew} & & \bypassWeird{\Andrew}
\end{tabular}
\end{document}
我期望该表的第二行和第三行有相同的结果。但似乎\exp_args:NV
只扩展了\l_ae_bypass
一次,\Andrew
然后就没有进一步扩展了。为什么?
重写
\DeclareExpandableDocumentCommand{\Andrew}{}{Andrew}
甚至
\def\Andrew{Andrew}
或者
\xdef\Andrew{Andrew}
并不能解决问题。
答案1
这正是应该发生的事情:V
-type 扩展为您提供存储在变量中的值。使用时流程
\bypassWeird{\Andrew}
是\l_ae_bypass
有内容的\Andrew
。所以当你这样做
\exp_args:NV \testingWeird \l_ae_bypass
这转换为
\testingWeird \l_ae_bypass { \Andrew }
并导致测试结果错误。如果你想进行详尽扩展,那么你必须
\tl_set:Nx \l_ae_bypass {#1}
但在您的情况下,这仍然会失败,因为您将其定义\Andrew
为文档命令(不可扩展)而不是变量(可扩展)。
(正如 Marco Daniel 所指出的,expl3
惯例是代码级变量名必须以类型结尾。所以你应该\l_ae_bypass_tl
在这里。)