\cs_new:Npn causa erro de unidade ou medida ilegal, enquanto \let não

\cs_new:Npn causa erro de unidade ou medida ilegal, enquanto \let não

No 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}

Se eu usar \cs_new:Npnem vez de \let, ocorrerá um erro de "unidade de medida ilegal". Por que? Como posso consertar isso?

Responder1

É um problema de sintaxe do TeX:

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

eu te mostrodefinir \foo:nn. Mas quando vocêchamarisso, você precisa fazer

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

e as chaves podem ser omitidas se o argumento consistir em um único token.

Em sua tentativa, de \bar:nn {3cm}{abcd}você obtém

\foo:nn 3cmabcd

assim #1é 3e #2é c, resultando em

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

o que definitivamente não é o que você deseja. Com

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

você obtém a coisa desejada.

Observado que \letnão deve ser utilizado onde \cs_new_eq:NNestá a chamada correta, vamos comparar as seguintes chamadas:

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

Existem diferenças? Bastante. Na primeira chamada, \bar:nnusaremos o significado \foo:nnatual no momento da chamada; com a segunda chamada, \bar:nnusará o significado de \foo:nnatual no momento da definição. Então você precisa saberpor quevocê faz essa definição e faz a escolha apropriada. Se você tem certeza de que o \foo:nnsignificado nunca muda, as duas chamadas são quase equivalentes: não completamente iguais, porque com 1 \bar:nnrequer uma etapa de expansão a mais do que com 2.

Observação.Desconsiderei alguns aspectos que não são relevantes para o assunto, mas são importantes.

  1. Tente seguir as expl3convenções de nomenclatura: ambos \foo:nne \bar:nnsão nomes ruins.

  2. Funções que empregam funções/macros não expansíveis, como \makeboxdevem ser “protegidas”:

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

    seria melhor.

informação relacionada