关于宏参数扩展的问题

关于宏参数扩展的问题

这个问题只是为了我自己理解扩展是如何工作的。

我在文档中使用 siunitx 包。为了确保与自己保持一致,我尝试将测量结果写成宏,这样就可以从一个地方全局更改它们。

我注意到,在其中一个宏的末尾添加一对括号{}会导致 siunitx 出错。看看以下 MWE:

\documentclass{article}

\usepackage{siunitx}

\begin{document}

\newcommand{\aMeasurement}{0.9(1)}

% This works fine
The answer was \num{\aMeasurement}.

% This gives an error
The answer was \num{\aMeasurement{}}.

\end{document}

我以为宏的参数在运行之前就已经完全展开了。如果是这样,怎么可能siunitx分辨出这两个调用之间的区别呢?

答案1

忽略具体细节,siunitx似乎对 TeX 的执行顺序存在一些误解。

首先,宏参数在宏调用之前不会扩展,只有在宏扩展后满足参数时才会扩展(如果有的话)。

您可以在

\def\foo#1{}


\foo{\somethingundefined}

\bye

\somethingundefined在调用之前不会扩展\foo(这会产生错误)事实上,由于\foo没有使用#1参数,所以根本不会扩展。

其次{},宏不是参数,除非宏被定义为接受参数(\aMeasurement你问题中的宏不接受参数)

\def\foo{hbox}


\foo

\foo{}

\foo\foo{}根本不等价,\foo扩展为hbox\foo{}扩展为hbox{}这些将采用非常不同的代码路径,例如

\csname\foo\endcsname

将执行命令\hbox ,但

\csname\foo{}\endcsname

将执行名称为的命令hbox{}(该名称之前未定义,其行为类似于\relax

答案2

您可能被这样的事实误导了:当在文本中使用无参数宏时,它后面应该跟一些使得 LaTeX 尊重其后空格的内容:

\LaTeX has macros

不会在徽标和“has”之间打印空格,而

\LaTeX{} has macros

打印正确。然而,这对空括号不是作为宏扩展的一部分被吞噬,因为 TeX 知道\LaTeX没有参数,所以它不会寻找参数。

如果定义宏如下,情况会有所不同

\newcommand{\foo}[1]{vim}

(未使用该参数)和

\vim{} can't be escaped from

确实会吞掉括号。例如,\edef\VIM{\foo{}}相当于\def\VIM{vim},因为括号作为参数替换的一部分消失。另一方面,

\vim\ can't be escaped from

将打印“vim” 和 “can't” 之间的空格,因为参数现在是“控制空间”,而宏会丢弃其参数。

您的输入\num{\aMeasurement{}}基本上相当于

\num{0.9(1){}}

并且您会收到错误消息

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!
! siunitx error: "invalid-token-in-number"
! 
! Invalid token '\q_recursion_tail ' in numerical input.
! 
! See the siunitx documentation for further information.
! 
! For immediate help type H <return>.
!...............................................  

所指的无效标记是左括号{。如果你滚动浏览错误,你会看到

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!
! siunitx error: "invalid-number"
! 
! Invalid numerical input '0.9(1){}'.
! 
! See the siunitx documentation for further information.
! 
! For immediate help type H <return>.
!...............................................  

这应该足够清楚了:\SI doesn't like at all the tokens{}`。

相关内容