在扩展为 cs 名称的表达式上调用 expl3 的 \use:c 会导致错误

在扩展为 cs 名称的表达式上调用 expl3 的 \use:c 会导致错误

如有任何关于如何调试或修复该问题的建议,我们将不胜感激。

\documentclass{minimal}
\usepackage{expl3}
\ExplSyntaxOn

\cs_new:Npn \__foo_aux:n #1{\c_novalue_tl}
\cs_set:Npn \__foo:n #1
{
    \cs_set:Npn \__foo_aux:n ##1{#1}
     __foo_aux:n
}

\begin{document}

% For comparison's sake:
\tl_new:N \__bar_tl
\tl_set:Nn \__bar_tl {__foo_aux:n}
\use:c{\__bar_tl}{X} % -No Value-

% The code that generates an error:
\\
\__foo_aux:n{X} % -No Value- %
\\ \__foo:n{(#1)} % __foo_aux:n % 
\\ \__foo_aux:n{X} % (X)
\\ \use:c{\__foo:n{(#1)}}{X} % Expected: (X)
% Console output
%! Missing \endcsname inserted.
%<to be read again> 
%                   \tex_long:D 
%l.22 \\ \use:c{\__foo:n{(#1)}}
%  {X} %! Missing \endcsname inserted.
\ExplSyntaxOff
\end{document}

答案1

\cs_new:Npn \__erwann_action:n #1 { \c_novalue_tl }
\cs_new_protected:Npn \erwann_set:n #1 { \cs_set:Npn \__erwann_action:n ##1 { #1 } }
\cs_new:Npn \erwann_do:n #1 { \__erwann_action:n { #1 } }
\cs_new_protected:Npn \erwann_do:nn #1 #2 { \erwann_set:n { #1 } \erwann_do:n { #2 } }

然后使用

\__erwann_action:n {X} % -No Value-
\erwann_do:n {X} % -No Value-
\erwann_set:n {(#1)} % just setup
\erwann_do:n {X} % (X)
\erwann_do:nn {(#1)} {X} % Expected: (X) OK

答案2

\use:c函数只是\csnameTeX 原语的包装器。TeXbook 中的描述非常清楚(第 40 页):

\csname相反,您可以通过说 ' ⟨tokens⟩ '从字符标记列表转到控制序列。出现在和\endcsname之间的此构造中的标记可能包含其他控制序列,只要这些控制序列最终扩展为字符而不是 TeX 基元;最终的字符可以是任何类别,不一定是字母。例如,' ' 本质上与 ' 相同;但 '是非法的,因为它扩展为包含基元的标记。此外,' ' 将产生不寻常的控制序列 ' ',即标记,您通常无法编写它。\csname\endcsname\csname TeX\endcsname\TeX\csname\TeX\endcsname\TeX\kern\csname\string\TeX\endcsname\\TeX|\TeX|

不仅上述行为\kern是违法的,而且任何不可扩展原语,例如\hbox\def。由于每个赋值都是用不可扩展原语进行的,因此 中不能进行赋值,\csname...\endcsname就像 的参数中不能进行赋值一样\use:c

可能有解决方法,但我不知道您会在什么情况下使用这个想法。

相关内容