\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並且#2如此c,導致

\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:nn2 需要多一個擴充步驟。

筆記。我忽略了一些與該問題無關的方面,但它們很重要。

  1. 嘗試並遵循expl3命名約定: 和\foo:nn都是\bar:nn不好的名字。

  2. 使用不可擴展函數/巨集的函數應\makebox受到“保護”:

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

    會更好。

相關內容