我的硬盘上有这段代码,现在我想理解它。首先我想知道这段代码是否正确和合乎逻辑,或者是否有其他方法可以做同样的事情。
\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
您将获得相同的输出,这说明了替换背后的想法。