\newcommand
我想知道 LaTeX在定义和使用/调用新宏方面的可能性和局限性。我知道其中一些示例很原始,但它们可以帮助理解局限性。我只对\newcommand
以“\”char+ 为名称的基本 s 感兴趣。
无效示例:
\newcommand{\newcenter}{center}
\begin{\newcenter}
\end{center}
\newcommand{\tabularthree}{{tabular}}
\begin \tabularthree {ccc}
cell& cell
\end \tabularthree
\newcommand{\tion}{tion}
\sec\tion{mysec}
有效示例:
\newcommand{\optarg}{[myoptarg]}
\section\optarg{mysec}
\newcommand{\cc}{cc}
\newcommand{\mybegin}{\begin}
\mybegin{tabular}{c\cc}
cell& cell
\end{tabular}
\newcommand{\tabulartwo}{tabular}
\begin{\tabulartwo} {ccc}
cell& cell
\end \tabulartwo
\newcommand{\tabularfour}{tabular}
\begin \tabularfour{ccc}
cell& cell
\end \tabularfour
答案1
Henri Menke 告诉了你如何绕过规则。这个答案将告诉你为什么你使用的语法(不)起作用。
无效的那些:
\newcommand{\newcenter}{center}
\begin{\newcenter}
\end{center}
这个命令失败了,因为\@currenvir
展开为\newcenter
,并且当 LaTeX 调用命令时\@checkend
,它会比较 的含义\@currenvir
和 的参数\end
,即center
。比较失败是因为它\newcenter
与进行center
比较而没有进一步展开,因此它们不同,并引发错误。另一方面,错误消息完全展开,\@currenvir
并且错误消息具有误导性:
! LaTeX Error: \begin{center} on input line 29 ended by \end{center}.
\newcommand{\tabularthree}{{tabular}}
\begin \tabularthree {ccc}
cell& cell
\end \tabularthree
这个会失败,因为 LaTeX 会检查环境是否存在,\ifcsname
它会构建一个命令,其参数为\begin
,在本例中为\tabularthree
,它会扩展为{tabular}
。\ifcsname
然后检查名为的命令{tabular}
,它不存在,然后 LaTeX 会告诉你:
! LaTeX Error: Environment {tabular} undefined.
\newcommand{\tion}{tion}
\sec\tion{mysec}
这个命令失败了,因为它是无效的。该命令\sec
被展开,并且它是割线函数,只允许在数学模式下使用,因此 TeX 认为你忘记了$
:
! Missing $ inserted.
<inserted text>
$
l.46 \sec
如果\sec
不是数学模式命令,TeX 会尝试执行它。如果它有一个参数,参数将是命令\tion
,然后将其扩展为tion
,然后\sec
命令将使用 执行其操作(无论它是什么)tion
。如果它不存在,TeX 会抱怨它\sec
不存在。
那个作品:
\newcommand{\optarg}{[myoptarg]}
\section\optarg{mysec}
这个编译,但它并没有产生你期望的结果。可选参数的测试失败,因为的代码\section
没有看到[
字符(并且它没有扩展\optarg
来寻找它),所以它将其\optarg
作为强制参数,并且该部分的标题变为[myoptarg]
并mysec
写在下面。
那些做工作:
\newcommand{\cc}{cc}
\newcommand{\mybegin}{\begin}
\mybegin{tabular}{c\cc}
cell& cell
\end{tabular}
这个方法有效,因为 TeX 在扩展时\mybegin
只会找到\begin
。TeX 随后继续扩展\begin
并正常执行操作。这个\cc
方法有效,因为tabular
它扩展了对齐前导的标记。
\newcommand{\tabulartwo}{tabular}
\begin{\tabulartwo} {ccc}
cell& cell
\end \tabulartwo
这个方法有效,原因和第一个方法无效相同。对\tabulartwo
和执行环境名称检查\tabulartwo
,它们是同一件事。而且那里的括号没有区别,因为根据 TeX 的参数抓取规则,正常参数要么是单个标记(\tabulartwo
是单个标记),要么如果{
找到一个左括号(),则参数是<balanced text>
该括号对内的(\tabulartwo
和在一对括号内)tabular
。<balanced text>
\newcommand{\tabularfour}{tabular}
\begin \tabularfour{ccc}
cell& cell
\end \tabularfour
同上。
但是你真的不应该为命令发明语法,因为即使它有效,你也会混淆你的代码,甚至几周后你都不会理解它。
答案2
\expandafter
解决了几乎所有的问题。你似乎是一个 LaTeX 初学者,所以这些不是你通常必须做的事情。还请查看何时使用 \edef、\noexpand 和 \expandafter?
\documentclass{article}
\begin{document}
\newcommand{\newcenter}{center}
\expandafter\begin\expandafter{\newcenter}
\end{center}
\newcommand{\tabularthree}{{tabular}}
\expandafter\begin\tabularthree{ccc}
cell& cell
\expandafter\end\tabularthree
\newcommand{\tion}{tion}
\csname sec\tion\endcsname{mysec}
\end{document}