为什么下面的代码不起作用?
\Requirepackage{amsthm}
\renewcommand\newtheorem[2]{%
\NewEnviron{\csname #1\endcsname}[1]{%
##1 : \BODY
}
}
我见过使用\csname SOMENAME\endcsname
不带参数的 for 宏的示例,但我不知道如何使用带有多个参数的\NewEnviron
或 来执行此操作\newcommand
。系统提示我出现错误! Missing \endcsname inserted
。
答案1
您不需要将命令名称用作环境名称。只要名称即可。
因此,你可以这样做:
\documentclass{article}
\usepackage{amsthm,environ}
\renewcommand\newtheorem[2]{%
\NewEnviron{#1}[1]{%
##1 : \BODY
}%
}
\begin{document}
\newtheorem{acorns}{oaks}
\begin{acorns}{trees}
leaves and things
\end{acorns}
\end{document}
请注意,此代码不需要阿姆斯特丹\newcommand\newtheorem...
,除非您因为其他原因需要该包,否则您可以使用。
此外,即使您创建了命令,第二个参数也是必需的,但您永远不会对它执行任何操作。在上面的例子中,对 执行了任何操作oaks
。
我不确定这是否真的是你想要做的。上述代码的输出是:
作为Christian Hupfer 指出,这当然会破坏\newtheorem
标准意义上的一切使用。埃格尔说,完全看不出\newtheorem
这种重新定义的目的是什么。这似乎迟早会惹上麻烦……可能很快就会。
答案2
为什么下面的代码不起作用?
让我们仔细看看\NewEnviron
:
经过一个简短的宏链来正确解析用户输入后,就开始\NewEnviron
使用了。\env@newenvironment
\let
\newenvironment
现在,\newenvironment
内部除了其他事情外(稍微简化了)还做了类似的事情
\expandafter\def\csname <env-name>\endcsname{<begin-code>}
(基本上,你做了正确的事情,但你不知道内部人员已经在处理这个问题了。)
如果您设置“ <env-name>=\csname SOMENAME\endcsname
”——这将导致使用您的自定义宏\newtheorem{SOMENAME}{}
——您最终会得到一对多余的\csname...\endcsname
:
\expandafter\def\csname\csname SOMENAME\endcsname\endcsname...
\expandafter
(您可能知道)在这种情况下,它会抓取\def
并存储它以向前查看下一个标记并首先扩展它。在这里,它会查找\csname
下一个标记\endcsname
并扩展其间的所有内容,并从中形成一个控制序列。这将是另一个\csname
再次被尾随的正确终止的标记\endcsname
。因此,您实际上将\csname
机制两次应用于“SOMENAME”,这意味着您最终不会得到\def\SOMENAME{<begin-code>}
(如您计划的那样),而是
\def\<expansion of \SOMENAME>{<begin-code>}
如果\SOMENAME
定义了,我们就不会有问题:
\documentclass{article}
\usepackage{environ}
\def\SOMENAME{somename}
\NewEnviron{\csname SOMENAME\endcsname}{somename-content: \BODY}
\begin{document}
\begin{somename}
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
Integer feugiat tempus urna, cursus placerat sapien mollis ac.
Donec a accumsan orci, in tristique ligula.
\end{somename}
\end{document}
但你应该不是定义它;这个用户界面可能会产生误导。只需使用与输入环境名称\NewEnviron
完全相同的方式:\newenvironment
\documentclass{article}
\usepackage{environ}
\newcommand{\FlorianEnvdefWrapper}[1]{%
\NewEnviron{#1}[1]{##1: \BODY}
}
\FlorianEnvdefWrapper{somename}
\begin{document}
\begin{somename}{foo-bar}
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
Integer feugiat tempus urna, cursus placerat sapien mollis ac.
Donec a accumsan orci, in tristique ligula.
\end{somename}
\end{document}
评论
我更改了示例宏的名称以避免与amsthm
包发生冲突。我认为总体上最好保持原样。当然也有例外,但如果您可以通过为命令选择另一个名称来避免这种情况,那么完全失去其功能可能不是最好的选择。