我不明白 \ifx 如何与宏定义交互。这是一个最小的例子:
\def\a#1{\b}
\def\b#1#2{[#1:#2]}
\a ABC
输出结果与预期一致。如果我将[B:C]
的定义更改为\a
\def\a#1{\ifx E#1\else \b\fi}
然后输出变成[:B]C
。空参数从何而来\b
,我该如何摆脱它?
我很抱歉问了一个之前肯定有人在这个网站上问过的问题。我努力寻找答案,但徒劳无功。谢谢!
答案1
和
\def\a#1{\ifx E#1\else \b\fi}
调用\a ABC
将A
作为参数\a
,因此输入流变为
\ifx EA\else\b\fi BC
并且由于条件为假,输入流中剩余的是
\b\fi BC
因此的参数\b
是#1<-\fi
和#2<-B
,所以我们得到
[\fi:B]C
现在\fi
履行消失的义务,你得到
[:B]C
如果你定义
\def\a#1{\ifx E#1\else\expandafter\b\fi}
经过条件判断后我们得到
\expandafter\b\fi BC
让\expandafter
产品\fi
消失前 \b
被展开,所以我们发现
\b BC
最后
[B:C]
在这种情况下\a EBC
,第一步将得到
\ifx EE\else\b\fi BC
变成
\else\b\fi BC
的扩展\else
会抛弃匹配之前的所有内容\fi
,我们只需得到
BC
查看日志文件有助于\tracingmacros=1
:
\tracingmacros=1
\def\a#1{\ifx E#1\else \b\fi}
\def\b#1#2{[#1:#2]}
\a ABC
将产生
\a #1->\ifx E#1\else \b \fi
#1<-A
\b #1#2->[#1:#2]
#1<-\fi
#2<-B
这准确地表明了我无需进行实验就做出的诊断。
如果你还添加\tracingifs=1
(使用基于 e-TeX 的引擎,例如pdftex
),你会得到
\a #1->\ifx E#1\else \b \fi
#1<-A
{vertical mode: \ifx: (level 1) entered on line 4}
{\else: \ifx (level 1) entered on line 4}
\b #1#2->[#1:#2]
#1<-\fi
#2<-B
{horizontal mode: \fi: \ifx (level 1) entered on line 4}
答案2
\b
抓住\fi
但如果您使用以下定义\a
,您将获得预期的输出:
\def\a#1{\ifx E#1\else \expandafter\b\fi}
以上完成了\if..\fi
处理之前的条件\b
。
\documentclass{article}
\begin{document}
\def\a#1{\b}
\def\b#1#2{[#1:#2]}
\a ABC
\def\a#1{\ifx E#1\else \b\fi}
\a ABC
\def\a#1{\ifx E#1\else \expandafter\b\fi}
\a ABC
\end{document}
如果您希望看到这一点,请使用以下的定义\b
并检查和.log
中包含的值:\argA
\argB
\def\b#1#2{%
\def\argA{#1}\show\argA%
\def\argB{#2}\show\argB%
[#1:#2]}
对于上面的第二次调用\a
,你会发现
> \argA: macro
-> \fi .
> \argB: macro
-> B.