如果在 \cs_new(_protected) 中使用,\IfNoValue(TF) 不会在文档级别检测 -NoValue-

如果在 \cs_new(_protected) 中使用,\IfNoValue(TF) 不会在文档级别检测 -NoValue-

我想我的问题与来自 xparse 的命令在由 \cs_new:Npn? 创建的函数内但我还是不明白发生了什么:在下面的 WE(不是最小的,对此感到抱歉)中,为什么\IfNoValueF没有检测到-NoValue-

\documentclass{article}
\usepackage[margin=0pt,paperheight=5cm]{geometry}
\usepackage{xparse}
\usepackage{datatool}

\ExplSyntaxOn

\DTLnewdb{instrumentsdb}

\cs_new_protected:Nn \mypkg_add_instrument:nnn
{%
  \DTLnewrow{instrumentsdb}%
  \DTLnewdbentry{instrumentsdb}{status}{#1}%
  \DTLnewdbentry{instrumentsdb}{name}{#2}%
  \DTLnewdbentry{instrumentsdb}{family}{#3}%
}

\NewDocumentCommand \brass {om}
{
  \mypkg_add_instrument:nnn {#1}{#2}{brass}%
}

\NewDocumentCommand \strings {om}
{
  \mypkg_add_instrument:nnn {#1}{#2}{strings}
}

\cs_new_protected:Nn \mypkg_display_instrument:nn
{%
  #2%
  \IfNoValueF {#1} {\\(#1)~(should~appear~only~if~"NoValue"~is~false) }%
}

\NewDocumentCommand \displayinstruments {}
{%
  \begin{description}
  \item[Brass]\
    \begin{itemize}
      \DTLforeach*[\DTLiseq{\tl_mypkg_family}{brass}]{instrumentsdb}{%
        \tl_mypkg_status=status%
        ,\tl_mypkg_name=name%
        ,\tl_mypkg_family=family%
      }{%
      \item\mypkg_display_instrument:nn {\tl_mypkg_status}{\tl_mypkg_name}%
      }
    \end{itemize}
  %
  \item[Strings]\
    \begin{itemize}
      \DTLforeach*[\DTLiseq{\tl_mypkg_family}{strings}]{instrumentsdb}{%
        \tl_mypkg_status=status%
        ,\tl_mypkg_name=name%
        ,\tl_mypkg_family=family%
      }{%
      \item\mypkg_display_instrument:nn {\tl_mypkg_status}{\tl_mypkg_name}%
      }
    \end{itemize}
  \end{description}
}
\ExplSyntaxOff
%
\begin{document}
\brass[new]{trumpet}
\brass[used]{trombone}
%
\strings[used]{guitar}
\strings{violin}
%
\displayinstruments
\end{document}

在此处输入图片描述

https://tex.stackexchange.com/a/94827/18401

  • 建议\NoValue在接口转换中测试 ,即在文档级命令的定义范围内。但是,正如我在示例中指出的那样,这会导致代码重复:可以想象有超过\brass\strings需要测试 的文档级命令 \NoValue
  • 提出了一个替代方案:

    \NewDocumentCommand { \foo } { O { } m }
      { \mypkg_foo:nn {#1} {#2} }
    

    因为我们不关心是否#1存在,所以我们只是设置一个空的默认值。但它的“空性”也无法测试,正如以下类似的 WE 所指出的那样。


\documentclass{article}
\usepackage[margin=0pt,paperheight=10cm]{geometry}
\usepackage{xparse}
\usepackage{datatool}

\ExplSyntaxOn

\DTLnewdb{instrumentsdb}

\cs_new_protected:Nn \mypkg_add_instrument:nnn
{%
  \DTLnewrow{instrumentsdb}%
  \DTLnewdbentry{instrumentsdb}{status}{#1}%
  \DTLnewdbentry{instrumentsdb}{name}{#2}%
  \DTLnewdbentry{instrumentsdb}{family}{#3}%
}

\NewDocumentCommand \brass {O{}m}
{
  \mypkg_add_instrument:nnn {#1}{#2}{brass}%
}

\NewDocumentCommand \strings {O{}m}
{
  \mypkg_add_instrument:nnn {#1}{#2}{strings}
}

\cs_new_protected:Nn \mypkg_display_instrument:nn
{%
  #2%
  \IfNoValueF {#1} {\\(#1)~(should~appear~only~if~"NoValue"~is~false) }%
  \tl_if_empty:nF {#1} { \\(#1)~(should~appear~only~if~false~"empty") }%
  \tl_if_blank:nF {#1} { \\(#1)~(should~appear~only~if~false~"blank") }%
}

\NewDocumentCommand \displayinstruments {}
{%
  \begin{description}
  \item[Brass]\
    \begin{itemize}
      \DTLforeach*[\DTLiseq{\tl_mypkg_family}{brass}]{instrumentsdb}{%
        \tl_mypkg_status=status%
        ,\tl_mypkg_name=name%
        ,\tl_mypkg_family=family%
      }{%
      \item\mypkg_display_instrument:nn {\tl_mypkg_status}{\tl_mypkg_name}%
      }
    \end{itemize}
  %
  \item[Strings]\
    \begin{itemize}
      \DTLforeach*[\DTLiseq{\tl_mypkg_family}{strings}]{instrumentsdb}{%
        \tl_mypkg_status=status%
        ,\tl_mypkg_name=name%
        ,\tl_mypkg_family=family%
      }{%
      \item\mypkg_display_instrument:nn {\tl_mypkg_status}{\tl_mypkg_name}%
      }
    \end{itemize}
  \end{description}
}
\ExplSyntaxOff
%
\begin{document}
\brass[new]{trumpet}
% \brass[used]{trombone}
%
\strings[used]{guitar}
\strings{violin}
%
\displayinstruments
\end{document}

在此处输入图片描述

答案1

为了理解你的代码有什么问题,我添加了一个\tl_show:n

\cs_new_protected:Nn \mypkg_display_instrument:nn
  {
    \tl_show:n {#1}
    #2
    \IfNoValueF {#1} {\\(#1)~(should~appear~only~if~"NoValue"~is~false) }
  }

这将表明你是不是得到-NoValue-#1你正在得到\tl_mypkg_status。这正是你所期望的

\mypkg_display_instrument:nn { \tl_mypkg_status } { \tl_mypkg_name }

也许你正在寻求通过这些变量成立

\mypkg_display_instrument:VV \tl_mypkg_status \tl_mypkg_name

\cs_generate_variant:Nn \mypkg_display_instrument:nn { VV }

但请注意,我会非常谨慎地-NoValue-以你的方式进行存储:它旨在用作文档界面标记,应在内部转换为更合适的形式。例如,由于你存储了某些东西丢失的事实,我更倾向于根本不存储它并在恢复时拾取它。

相关内容