l3prop - 获取宏内的条目失败

l3prop - 获取宏内的条目失败

在以下示例中,我定义了两个新宏\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\UseLengthf-

请注意,由于 TeX 在这里寻找一个数字,\protected状态对扩展没有影响。

相关内容