以下示例如果为假 且 之前未初始化,\def\a...
则失败。相反,如果为真,则 可以在 之前或 之后初始化。\ifabc
\myif
\def\a...
\ifabc
\myif
\def\a...
我不清楚为什么当\ifabc
为真且\myif
之前未初始化时它不会失败\def\a
。
\newif\ifabc
\abctrue % \abcfalse
%\let\myif=\iftrue
\ifabc
\def\a#1#2{\myif#1\else#2\fi}
\fi
%\let\myif\iftrue
\ifabc
\a{hello}{world}
\fi
\end
答案1
这是对cfr 的答案。
TeX Book 在第 20 章中提到了以下内容定义(也称为宏)(第 210 页)
请注意,所有条件控制序列都以 开头
\if...
,并且都有一个匹配的\fi
。这种约定 - 即 和\if...
配对\fi
- 使您更容易看到程序中条件的嵌套。 的嵌套\if...\fi
独立于 的嵌套{...}
;因此,您可以在条件的中间开始或结束一个组,也可以在组的中间开始或结束一个条件。丰富的宏使用经验表明,这种独立性在应用程序中非常重要;但如果您不小心,它也会导致混乱。
嗯...大家要小心。:)请注意,您有一种嵌套\if...\fi
和分组的形式{...}
。
另见(第 213 页):
当
\if...
扩展时,TeX 会尽可能向前读取,以确定条件是真还是假;如果为假,它会向前跳过(跟踪\if...\fi
嵌套),直到找到\else
、\or
或\fi
来结束跳过的文本。同样,当\else
、\or
或\fi
扩展时,TeX 会读取到任何应该跳过的文本的末尾。
根据以上信息,我们发现在 下\abcfalse
,TeX“跳过 ... 直到找到\else
结束跳过文本的 ...”,而不考虑任何分组。因此,扩展以#2
在垂直模式下评估宏参数结束。
我们还可以使用追踪(某种程度上)发生了什么:
1: \documentclass{article}
2:
3: \begin{document}
4:
5: \newif\ifabc% Default is \abcfalse
6:
7: %\let\myif=\iftrue
8:
9: \tracingifs1
10: \ifabc
11: \def\a#1#2{\myif#1\else#2\fi}
12: \fi
13:
14: %\let\myif\iftrue
15:
16: \ifabc
17: \a{hello}{world}
18: \fi
19:
20: test
21:
22: \end{document}
跟踪结果\else
显示(仍处于垂直模式)位于第 10 行的语句中\if...
:
{vertical mode: \iffalse: (level 1) entered on line 10}
{\else: \iffalse (level 1) entered on line 10}
! You can't use `macro parameter character #' in vertical mode.
l.11 \def\a#1#2{\myif#1\else#
2\fi}
Sorry, but I'm not programmed to handle this case;
I'll just pretend that you didn't ask for it.
If you're in the wrong mode, you might be able to
return to the right one by typing `I}' or `I$' or `I\par'.
答案2
我思考...
... 当 时\abctrue
,条件成立,所以\def
执行。因此,TeX 不会尝试执行 的内容,\def
直到实际使用宏为止。
但是,当 时\abcfalse
,它必须通读 的内容来\def
寻找\else
。由于\myif
不是条件语句,因此它无法意识到 是\else
嵌套的。因此,它会读取 之后的内容\else
作为它要执行的内容,因为\abcfalse
。这会失败,因为#2
不能在这里使用。
尝试
\def\a#1#2{\myif#1\else\show\super#2\fi}% but not for real - never \def a single letter macro name unless you are really, really sure you want to overwrite anything it alreay means.
看看发生了什么:
> \super=undefined.
l.153 \def\a#1#2{\myif#1\else\show\super
#2\fi}
?
! You can't use `macro parameter character #' in vertical mode.
l.153 \def\a#1#2{\myif#1\else\show\super#
2\fi}
相反,如果您在and set\show\super
之前有,那么除非您实际使用了定义的宏,否则它将永远不会被执行。\else
\abctrue