争论在哪里?

争论在哪里?

我的硬盘上有这段代码,现在我想理解它。首先我想知道这段代码是否正确和合乎逻辑,或者是否有其他方法可以做同样的事情。

\documentclass{article}
\usepackage{fp}

\newcommand*\macro[2][]{%
  Option : #1\par % print the option in #1
  \let\y #2 % to keep 
\begingroup
  \catcode`\(=1
  \catcode`\)=2
  \macrobis
}
\newcommand*\macrobis[1]{%
\endgroup
\scantokens{\def\temp{#1}}}

\begin{document}

\def\fct{x*x}

\macro[op]{\fct}(exp(1))

\FPeval\x{\temp}%
\FPeval\img{\y}%
x = \x\ donne  y = \img

\end{document}

\begingroup\endgroup我猜是因为代码改变了 catcodes,但 macrobis 的调用非常奇怪。参数在哪里?有人能解释一下这段代码吗?

答案1

让我们一次看一个命令:

\newcommand*\macro[2][]{%
  Option : #1\par % print the option in #1
  \let\y #2 % to keep 
\begingroup
  \catcode`\(=1
  \catcode`\)=2
  \macrobis
}

\macro有一个可选参数(默认为空)和一个强制参数。它假定强制参数是token,就像它所做的那样\let\y#2(但会在输入流中留下一个空格)。然后它打开一个组,在其中设置()作为分隔符,就像{和一样};之后它调用\macrobis

\newcommand*\macrobis[1]{%
\endgroup
\scantokens{\def\temp{#1}}}

\macrobis将其参数视为(括号)。然后它结束该组,因此()返回到它们之前的状态并定义\temp为扩展到#1但在内部,\scantokens因此可能的()中的字符#1将在此设置中重新扫描,其中它们不再是分隔符。

看起来是括号中的第二个强制参数\macro实际上是的参数\macrobis,但从用户的角度来看这并不相关。

重点是隐藏该参数中可能的括号:如果定义了

\newcommand*\macro[2][]{%
  Option : #1\par % print the option in #1
  \let\y #2 % to keep 
  \macrobis}
\def\macrobis(#1){\def\temp{#1}}

那么诸如的输入\macro[op]{\fct}(exp(1))就会被解释exp(1为的参数\macrobis,这是错误的。

答案2

据我理解,宏(或控制序列)可以被视为更大构造的“替代品”(此处“更大构造”指宏内容)。因此,\macro吞噬\macro[op]{\fct}(因为它需要 2 个参数),做一些神奇的事情,并将其替换为\macrobis。输入流中仍然剩下的是(exp(1))类别代码更改为()分别对开头和结尾进行分组。因此,实际上你只剩下\macrobis{exp(1)},它代表了 的有效输入\macrobis,因为它需要一个参数。

与此相关,请考虑以下内容。\FPeval是一个接受两个参数的宏,如下所述\show\FPeval

> \FPeval=macro:
#1#2->\FP@eval {#1}{#2}.

但是如果你定义

\newcommand{\myfunc}{\FPeval}

现在\myfunc不需要参数,而是使用

\myfunc\x{\temp}%
\myfunc\img{\y}%
x = \x\ donne  y = \img

您将获得相同的输出,这说明了替换背后的想法。

相关内容