有人可以解释一下 Futurelet 吗之内对齐环境?
例子:
如果下一个字符是 {,则命令 \A 应该返回“A”,如果是 &,则返回“B”,在其他情况下返回“C”。
\gdef\A{\futurelet\thesymbol\B}
\gdef\B#1{\ifx\bgroup\thesymbol A\else\ifx&\thesymbol B\else C\fi\fi}
对于普通文本或内联数学,它工作得很好:
\A{a},\A&,\A a % -> "A,B,C"
$\A{a}$,$\A&$,$\A a$ % -> "A,B,C"
但当我在 align* 环境 (amsmath) 中使用它时,出现“不完整的 \ifx”错误:
\begin{align*} \A{a},\A&,\A a \end{align*}% --> error.
有人能给我解释一下吗?谢谢!
克里斯
PS:关于对齐环境中的 Futurelet,还有更多我不明白的事情:如果我们定义
\gdef\A{\futurelet\thesymbol\alpha}
\gdef\D#1{\detokenize{#1}}
然后
\begin{align*}
\D&,\A a % -> "&,alpha a" (okay)
\A a,\D{&} % -> "alpha a,&" (okay)
\A a,\D& % -> error: "Argument of D has an extra }." (???)
\end{align*}
答案1
\gdef\B#1{\ifx\bgroup\thesymbol A\else\ifx&\thesymbol B\else C\fi\fi}
当 TeX 看到时,&
它会将模板的其余部分交换为\halign
latex 大小写等所指定的内容c
r
,因此\ifx
会比较模板的前两个标记(可能\unskip
然后\hfil
单元格(以及组)将结束出错。
如果你想&
在未来测试之前开始一个小组并在测试结束后结束它时隐藏它,你需要
{\ifnum0=`}
...
\ifnum0=`{\fi}
出现在任何表格代码中的形式。
这会产生 A、B、C,我认为这就是预期的结果。
\documentclass{article}
\usepackage{amsmath}
\gdef\A{{\ifnum0=`}\fi\futurelet\thesymbol\B}
\gdef\B#1{\ifx\bgroup\thesymbol A\else\ifx&\thesymbol B\else C\fi\fi \ifnum0=`{\fi}}
\begin{document}
\begin{align*} \A{a},\A&,\A a \end{align*}
\end{document}
对于你的第二个例子,注意&
结束一个组
a,\D&
就像{\D}
并且都给出相同的错误:
! Argument of \D has an extra }.
<inserted text>
\par
l.15 {\D}
{\D}
由于不清楚您想要做什么,因此无法清楚找到解决方法。
答案2
我无法与 David 竞争对 TeX 代码的理解,所以我不会尝试修复你的宏(尽管我的观点是,你所做的从根本上来说并不明智)。但是,他关于“当 TeX 看到 ”的评论&
可以扩展如下。在扫描对齐时,TeX 的行为方式与大多数用户(甚至是经验丰富且知识渊博的用户)对其执行的心理模型有些不一致。也就是说,我们想象TeX 总是在做以下三件事之一:
扫描输入,将字符标记化,为宏解析器“嘴巴”提供食物;
扩展宏;
执行不可扩展的标记:像
\def
或 这样的编程指令\hbox
,或者像字符这样的直接排版命令。
在这个模型下,每个人都期望在对齐(TeX 基元\halign
或\valign
)中,制表符&
在第 3 点(执行)下采取行动。然而,事实并非如此;事实上,TeX 在第 1 点“注意到”了制表符!如果 TeX曾经读过一个与号(或等效类别的字符)它将立即结束当前单元格、关闭一个组、插入v
模板的“部分”等等。
(编辑:我只是浏览了一下errorlog.pdf
(即texdoc errorlog
),发现了 1978 年 3 月 18 日调试会话中的相关评论:
让获取下一个例程拦截
&
和\cr
标记。我以为我可以将&
和\cr
放入big_switch
[即 TeX 的胃中,而不是眼睛中];这是一个巨大的错误。
这是一个有趣的部分见解,可以了解是什么导致 Knuth 对这些数组标记做出上述看似奇怪的行为选择,以及确认这确实是行为。)
当然,例外情况是当 TeX 位于未完成的括号组内时(并且必须是实际的括号字符,而不是隐式字符或\begingroup
来启动这个组),这导致 David 的{\ifnum0=
}` 构造可扩展地等同于一个开放括号,而无需在可能放置它的宏定义内实际创建不平衡的括号。
这种奇怪的解析规则的结果是,人们必须非常小心地对待表格单元格中的宏读取的内容,或环境中包含的内容。像你这样的宏,实际上是通过赋值而不是宏参数解析来读取参数的,这就更加危险了,因为如果没有必要的括号,可以读取的制表符将不是受到保护。与表格兼容的环境包括该\ifnum
功能,以便保护其中可能出现的任何制表符;更简单的环境将跨单元格拆分,因此可能会失败。