在以下示例中,我定义了两个新宏\UseLength
和\xUseLength
。这两个宏都将把键的存储值放回到输入流中。宏\UseLength
按预期工作。第二个宏首先测试键是否存在。但是,如果我使用宏,\xUseLength
就会出现缺陷:
! Missing number, treated as zero.
<to be read again>
\tex_long:D
l.30 foo \hspace{\xUseLength{dim}{width}}
bar
为什么这个例子会失败?
这里是 MWE:
\documentclass{article}
\usepackage{xparse,}
\ExplSyntaxOn
\prop_new:N \l_md_dim_prop
\prop_new:N \l_md_skip_prop
\prop_put:Nnx \l_md_dim_prop { width } { 2cm }
\prop_put:Nnx \l_md_skip_prop { above } { 1cm~plus~0.2cm }
\NewDocumentCommand \UseLength { m m }
{
\prop_get:cn { l_md_#1_prop } { #2}
}
\NewDocumentCommand \xUseLength { m m }
{
\prop_get:cnNTF
{ l_md_#1_prop } { #2 }
\l_tmpa_tl
{ \tl_use:N \l_tmpa_tl }
{\msg_term:n {no~entry~in~prop}~1cm }
}
\ExplSyntaxOff
\begin{document}
foo \hspace{\UseLength{dim}{width}} bar
%foo \hspace{\xUseLength{dim}{width}} bar
\end{document}
答案1
您要实现的目标是编写完全可扩展的函数(这相当棘手,而且通常不是最好的方法)。\hspace
正在寻找一个维度,并且必须在没有任何阻止扩展(例如分配)的情况下实现。因此,诸如 之类的东西\prop_get:cnNTF
根本无法使用。剩下的是相当慢的东西,例如\prop_get:cn
。此外,还必须检查
- 使用的属性列表实际上是属性列表吗?
- 键是否在属性列表中?(如果不是,我们会得到一个空值,因此对于某些应用程序来说,这甚至不是一个可以回答的问题)
因此这里有一些“有点”有效的东西
\documentclass{article}
\usepackage{xparse,}
\ExplSyntaxOn
\prop_new:N \l_md_dim_prop
\prop_new:N \l_md_skip_prop
\prop_put:Nnx \l_md_dim_prop { width } { 2cm }
\prop_put:Nnx \l_md_skip_prop { above } { 1cm~plus~0.2cm }
\NewDocumentCommand \UseLength { m m }
{
\prop_get:cn { l_md_#1_prop } { #2}
}
\cs_generate_variant:Nn \tl_if_empty:nTF { f } % we need that variant below
\NewDocumentCommand \xUseLength { m m }
{
\prop_if_exist:cTF { l_md_#1_prop } % we need to check this as \prop_get:cn does not create a property list but just blows up
{
\tl_if_empty:fTF % return value is empty but only if we do "f" expansion
{ \prop_get:cn { l_md_#1_prop } { #2} }
{ 1cm
\msg_term:n {no~entry~in~#1~ for~ #2}
}
{ \prop_get:cn { l_md_#1_prop } { #2} }
}
{ 1cm
\msg_term:n {undefined~ property~ store:~ #1}
}
}
\ExplSyntaxOff
\begin{document}
foo \hspace{\UseLength{dim}{width}} bar \par
foo \hspace{\xUseLength{dim}{width}} bar \par
foo \hspace{\xUseLength{dim}{xwidth}} bar \par
foo \hspace{\xUseLength{xdim}{width}} bar \par
\end{document}
错误恢复仍然存在疑问,因为它可能发生在仍然崩溃的地方,但对于类似的情况\hspace
它就会发生。
答案2
您无法执行此操作,因为在 ( -type) 扩展\hspace
后需要一个数字,并且不会产生数字,因为它包含一个赋值(应该分配给)。另一方面, type是可扩展的,因为其中没有赋值。f
\xUseLength
\prop_get:cnNTF
\l_tmpa_tl
\UseLength
f-
请注意,由于 TeX 在这里寻找一个数字,\protected
状态对扩展没有影响。