解决了

解决了

解决了

感谢@PhelypeOleinik 提供的解决方案!也感谢所有迅速提供帮助的人。对于以后看到这篇文章的人来说,这个错误实际上与 ConTeXt 无关,因此即使您使用 LaTeX 或纯 TeX,下面的解释也会很有用。

原始帖子

我正在 ConTeXt 中创建一个模块,该模块主要通过命令访问\setup<name>[](对于名为 的某个通用结构<name>)。除了这个命令和其他一些供最终用户使用的命令之外,我还为所有内部命令添加了命名空间前缀,但由于我希望此命令如何运行,我选择不使用 ConTeXt 的内置\installcommandhandler

尽管如此,除了一个非常恼人的与命名空间相关的错误,我几乎完成了整个事情,而我还没有能够解决它。有一次,我的一个命令调用了 和 ,由于命名空间前缀,\processcommacommand[<list>]<command>两者<list>都是<command>样式\csname,并且两者都需要用\expandafter链进行扩展。我已经隔离了有问题的部分并更改了下面的命令名称:

\unprotect

\installnamespace{nms}
%\def\????nms{@@@@nms} % For testing only
% A simpler namespace creator could just run e.g. \def\????nms{@@@@nms}, but since in
% practice the actual namespace installer won't determine the prefix string until runtime,
% I have to define everything as generally as possible below, in terms of
% \csname\????nms<other>\endcsname.

% ... other module code ...

% If #1 consists of <arg1A>,<arg1B>,... separated by commas, and #2 consists of
% <arg2Akey>=<arg2Aval>, <arg2Bkey>=<arg2Bval>,... separated by commas, the
% \<namespace>_processor command below attempts to create a series of commands like so:
% % \def\<namespace>@<tag>@<arg1A>@<arg2Akey>{arg2Aval}
% % \def\<namespace>@<tag>@<arg1B>@<arg2bkey>{arg2Bval}
% % etc.
% ...for some externally defined string \tag.

\expandafter\unexpanded\expandafter\def\csname\????nms _processor\endcsname[#1][#2]{%
    \expandafter\def\csname\????nms _params\endcsname##1{%
        \doifnotempty{##1}{\getparameters[\????nms @\tag @##1@][#2]}
    }
    \expandafter\def\csname\????nms _csvs\endcsname{#1}
    \expandafter\expandafter\expandafter\processcommacommand\expandafter\expandafter
        \expandafter[\expandafter\csname\????nms _csvs\endcsname\expandafter]%
        \csname\????nms _params\endcsname
    % The above should simplify to
    % % \processcommacommand[\<namespace>_csvs]\<namespace>_params,
    % ...but in practice it throws a "Missing \endcsname inserted" error.
}

% ... other module code ...

\protect
\endinput

但是,如果我将顶部的命名空间设置为由 定义,\def\????nms{@@@@nms}并将有问题的行(以 3 个\expandafter调用开头)替换为对命名空间前缀的直接引用(例如\processcommacommand[\@@@@nms_csvs]\@@@@nms_params),则整个模块都可以正常工作,这让我感到困惑,因为理论上这应该没有什么不同。我使用\expandafter不正确吗?我尝试重写该特定行几次,结果完全相同,所以我无法说出我在那里犯了什么错误(如果有的话)。

答案1

正如我在评论中所说,我是 ConTeXt 的 Jon Snow,所以这个答案是关于链条的\expandafter

您使用的第一个\expandafters 是正确的。最后一个是问题:

\expandafter\expandafter\expandafter\processcommacommand\expandafter\expandafter
    \expandafter[\expandafter\csname\????nms _csvs\endcsname\expandafter]
    \csname\????nms _params\endcsname

让我们来看看。第一个链扩展了突出显示的标记:

在此处输入图片描述

因此第一个链仅扩展\????nms并停止,所以我们剩下:

\expandafter\processcommacommand\expandafter
    [\csname<\????nms>_csvs\endcsname\expandafter]
    \csname\????nms _params\endcsname

其中<\????nms>表示 的一次展开。为了举例,\????nms我们假设\????nms展开为。NMS

然后,第二条链:

在此处输入图片描述

扩展\csname NMS_csvs\endcsname并停止,现在我们剩下:

\processcommacommand
    [\NMS_csvs\expandafter]
    \csname\????nms _params\endcsname

接下来执行的是\processcommacommand一些奇怪的参数。这不是我们想要的。

正确的\expandafter链条应该是:

\expandafter\processcommacommand\expandafter
  [\csname\????nms _csvs\expandafter\endcsname\expandafter]%
   \csname\????nms _params\endcsname

但为什么?

首先,你不需要扩展 中的元素\csname...\endcsname\csname原语将执行所有元素的完全扩展,直到下一个\endcsname,因此:

\def\my{MY}
\def\cmd{COMMAND}
\expandafter\def\csname\my\cmd\endcsname{Hello}
\MYCOMMAND

仅与一个 一起工作\expandafter

因此,在您的代码中,您只需扩展两者\csname,它们就会\????nms在需要时扩展。

第二点(也是第一点的结果)是,您可以\expandafter从 内部“继续”一个链\csname(它执行完全扩展,还记得吗?)。因此\csname\expandafter\endcsname\hello\hello在 之前扩展\csname

现在,写下来。我们从以下开始:

\processcommacommand
  [\csname\????nms _csvs\endcsname]%
   \csname\????nms _params\endcsname

首先,我们展开第一个\csname。只\expandafter需要两个:

\expandafter\processcommacommand\expandafter
  [\csname\????nms _csvs\endcsname]%
   \csname\????nms _params\endcsname

第一个会跳过\processcommacommand,第二个也会跳过[。现在我们处于 内部的完整扩展上下文中\csname。我们可以利用这一点来扩展下一个,方法是在 之前\csname插入一个并从这里继续链条:\expandafter\endcsname

\expandafter\processcommacommand\expandafter
  [\csname\????nms _csvs\expandafter\endcsname\expandafter]%
   \csname\????nms _params\endcsname

第一个\expandafter将跳过\endcsname,下一个将跳过]

相关内容