\cs_new:Npn 会导致非法单位或测量错误,而 \let 不会

\cs_new:Npn 会导致非法单位或测量错误,而 \let 不会

在 MWE 中:

\documentclass{article}
\setlength{\fboxsep}{0pt}
\begin{document}

\ExplSyntaxOn
\cs_new:Npn \foo:nn #1#2
  {
    \makebox[#1][s]{#2}
  }
% \cs_new:Npn \bar:nn #1#2 { \foo:nn #1#2 }
\let \bar:nn \foo:nn
\fbox{\foo:nn {3cm} {a~b~c~d}}\par
\fbox{\bar:nn {3cm} {a~b~c~d}}
\ExplSyntaxOff

\end{document}

如果我使用\cs_new:Npn而不是\let,它会抛出“非法计量单位”错误。为什么?我该如何解决这个问题?

答案1

这是 TeX 语法的问题:

\cs_new:Npn \foo:nn #1#2 { ... }

我展示给你定义 \foo:nn.但当你称呼你需要做的

\foo:nn {<argument 1>}{<argument 2>}

如果参数由单个标记组成,则可以省略括号。

在你的尝试中,\bar:nn {3cm}{abcd}你得到

\foo:nn 3cmabcd

也是,结果是#13#2c

\makebox[3][s]{c}mabcd

这绝对不是你想要的。

\cs_new:Npn \bar:nn #1#2 { \foo:nn {#1}{#2} }

你得到了想要的东西。

观察到\let不应该使用哪里\cs_new_eq:NN是正确的调用,让我们比较以下调用:

  1. \cs_new:Npn \bar:nn #1#2 { \foo:nn {#1}{#2} }
  2. \cs_new_eq:NN \bar:nn \foo:nn

有什么区别吗?有很多。第一次调用时,\bar:nn将使用调用时当前的含义\foo:nn;第二次调用时,\bar:nn将使用定义时当前的含义\foo:nn。所以你需要知道为什么你做了这样的定义并做了适当的选择。如果你确定\foo:nn永远不会改变含义,那么这两个调用几乎是等效的:并不完全相同,因为使用 1\bar:nn比使用 2 多需要一个扩展步骤。

笔记。我忽略了一些与问题无关的方面,但它们很重要。

  1. 尝试遵循expl3命名约定:和\foo:nn都是\bar:nn不好的名字。

  2. \makebox使用不可扩展函数/宏的函数应该受到“保护”,例如:

    \cs_new_protected:Npn \stephen_foo:nn #1#2 { \makebox[#1][s]{#2} }
    

    会更好。

相关内容