也许这个问题以前已经有人问过,但我无法找到正确的问题。
我无意中发现了这一点特征:
比如说,我想做一个
\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
。不要。