\end.... 宏名称在 LaTeX2e 中保留吗?

\end.... 宏名称在 LaTeX2e 中保留吗?

也许这个问题以前已经有人问过,但我无法找到正确的问题。

我无意中发现了这一点特征

比如说,我想做一个

\newcommand{\supersophisticatedmacroname}{Hello}

定义,然后是类似环境结束命令的东西

\endsupersophisticatedmacroname

但这失败了:

! LaTeX Error: Command \endsupersophisticatedmacroname already
defined.
               Or name \end... illegal, see p.192 of the manual.

如果我说“等等”,我可以理解错误消息,\newcommand{\endtable}因为这些名称当然是定义的,标志着环境的结束。但我很确定,在任何合理的类中都没有这样的命令(想想宏名称 ;-))。

是否LaTeX阻止以 开头的命令的定义\end...?为什么?只是为了使环境的概念实现更容易?

这是一个非 MWE

\documentclass{book}

\newcommand{\supersophisticatedmacroname}{Hello}%

\newcommand{\endsupersophisticatedmacroname}{World}% fails
\newcommand{\endandnowforsomethingcompletelydifferent}{World}% fails too.


\begin{document}%
Hello World

\supersophisticatedmacroname


\end{document}

Plain TeX 不会抱怨:

\def\supersophisticatedmacroname{Hello}%
\def\endsupersophisticatedmacroname{World}%



\supersophisticatedmacroname

\bye

编辑

正如 Manuel 在其评论中所说,

\def\endsupersophisticatedmacroname{...}

甚至可以在 LaTeX 中工作。

编辑

对我的问题有四个(!!)很好的答案——我曾经考虑过接受其中一个,而且我知道,这意味着,我必须‘让’另外三个同样高素质的用户‘失望’。

答案1

正如其他人指出的那样,您可能无法定义以 开头的任何命令\end。原因是您可以使用任何latex2e 命令作为环境(有些人不喜欢这种设计,但这就是它的设计方式),因此你可以

\begin{small}....\end{small}

尽管\endsmall通常没有定义。

如果你被允许去

\newcommand\endsmall{zzzz}

如果\endsmall没有定义,那么您将被允许重新定义环境small而不会发出任何警告。

答案2

简短回答:是的,至少就目前而言,LaTeX2e 确实保留了这些名称\newcommand。TeX\def原语没有这样的限制,如果您真的想要定义一个以 开始的命令\end...

LaTeX2efoo通过查找宏\foo和可能的宏来实现环境\endfoo。例如,这些是通过

\newenvironment{foo}{}{}

为了防止发生以下情况

\newcommand\endfoo{}

对此进行了检查并专门阻止。想象一下,例如,您不知道实施情况并执行了上述操作:如果没有检查,您将在两种情况之一中得到令人惊讶的结果。

这里的问题实际上是 LaTeX2e 对于什么算作环境相当“宽容”。没有针对实现的特定命名空间,您\endfoo根本无需定义。“LaTeX3 愿景”是为了正确解决这个问题:如果您看一下,xparse它确实有一个内置单独命名空间的想法,但当然目前必须定义与 LaTeX2e 兼容的命令。

答案3

该命令\newcommand{<cs>}...用于\@ifdefinable{<cs>}测试控制序列是否可用;定义是

\long\def\@ifdefinable #1#2{%
      \edef\reserved@a{\expandafter\@gobble\string #1}%
     \@ifundefined\reserved@a
         {\edef\reserved@b{\expandafter\@carcube \reserved@a xxx\@nil}%
          \ifx \reserved@b\@qend \@notdefinable\else
            \ifx \reserved@a\@qrelax \@notdefinable\else
              #2%
            \fi
          \fi}%
         \@notdefinable}

第一个部分

 \edef\reserved@a{\expandafter\@gobble\string #1}

生成不带反斜杠的宏名(至少如果\escapechar它具有其通常的值),将其存储在 中\reserved@a;然后将其输入到\@ifundefined。如果请求的宏通过测试,

\edef\reserved@b{\expandafter\@carcube \reserved@a xxx\@nil

执行,它存储在\reserved@b宏名称的前三个字符中(或者用 's 填充x以达到三个)。然后\reserved@b\@qend扩展为

% latex.ltx, line 794:
\edef\@qend{\expandafter\@cdr\string\end\@nil}

也就是说,它包含 的字符串化(类别代码 12)版本end。在这种情况下,它调用;如果完全包含\@notdefinable,它所做的操作也一样(不重新定义这个原语)。\reserved@a\relax

第二个参数是(经过修改的)定义文本,如果没有通过完整的测试,那么它将被吞噬。

可能重新定义\@qend为不能由 生成的任何东西\string,比如\def\@qend{$},并且能够定义名称以 开头的命令end。不要。

答案4

在 LaTeX2e 内核中latex.ltx\newcommand{<cs>}检查是否可以<cs>通过名为 的宏进行定义\@ifdefinable。其定义来自 LaTeX2e 内核文档/source2e(部分11.3 命令定义,第23页),有如下描述:

\@ifdefinable{NAME}{<YES>}

<YES>如果允许用户定义 则执行\NAME,否则会给出错误。\NAME如果\@ifundefined{NAME}为真、NAMErelax且 的前三个字母NAME不是end,则用户可以定义,如果\endNAME未定义 则执行。

相关内容