什么可以作为宏参数出现,什么不能作为宏参数出现?

什么可以作为宏参数出现,什么不能作为宏参数出现?

的文件环境包裹说

使用环境的优点是它们的内容不被视为宏参数,因此对其中存在的内容的限制更少,并且可以更有效地处理长篇文档文本。

然而,有时“扫描”大量代码、解析它们并“不执行任何操作”(除非满足某些条件)可能会很有用。在这样做时,重要的是要知道这是否会对其余代码施加限制。

具体来说,请考虑以下文档:

\documentclass{minimal}

\long\def\everything#1end@of@everything{#1}
\def\test{test1}

\begin{document}
\everything
Hello World!

\test

%%% Some
%%% other
%%% code
end@of@everything
\end{document}

这工作正常,但是使用这种宏的“危险”是什么?在“其他代码”中什么可以发生,什么不能发生?

我想到两件事:

  • 任何用 定义的东西\outer都会抛出错误(参见什么时候适合使用 \outer?

  • 可能会有内存问题,但是这些问题有多严重,例如参数的长度是否有限制?


编辑:@Joseph Wright 指出了嵌套和(重新)标记化问题(这可能是\collect@body为什么数学环境比我的宏更微妙地工作)。

不过,我仍然对“效率”方面感兴趣。这个例子来自@Yiannis Lazarides,我发现

\documentclass{minimal}

\long\def\everything#1end@of@everything{#1}

\usepackage{lipsum}

\begin{document}
\everything

\newcount\n
\n=0
\def\message{I can count to }
   \loop
   \ifnum\n<37000
   \advance\n by1
   \message\number\n : \lipsum[1-2]    

   \repeat
end@of@everything
\end{document}

仍然有效(产生了惊人的 11563 页输出 :)),这让我想知道是否真的有任何限制数量作为参数传递的数据。

答案1

这里的两个典型限制是逐字材料和嵌套。

如果您将材料作为宏参数抓取,则 TeX 会对其进行标记。即使使用 e-TeX(或写入外部文件),我们稍后重新标记的能力也是有限的。因此

\begin{foo}
  Some normal content
  \verb=%=
\end{foo}

(通常)可以很好地处理,而

\foo
  \verb=%=
@endfoo

不会。

在嵌套方面,使用分隔宏 TeX 将在第一个匹配处停止

\foo
  \foo
   stuff
  @endfoo
  morestuff
@endfoo

因此不会按预期运行,

\begin{foo}
  \begin{foo}
    stuff
  \end{foo}
  more stuff
\end{foo}

将要。

(我在这里使用了类似 LaTeX 的环境,但你当然也可以用纯 TeX、ConTeXt 来定义环境,ETC。具有同样的含义。

相关内容