基于 egreg 对我的替代解决方案上一个问题我从中学到将字符变成宏的想法,现在我为 bra-kets 定义了一种不同的语法,事实上我更喜欢这种语法。我的宏几乎有效(尽管这里有一点货物崇拜编程,因为我\begingroup\lccode
在我的宏中复制了他的解决方案中一些我不完全理解的部分 - 以...开头的两行 - 对它们进行了稍微的改动;我怀疑问题就在那里,因为我相信其余部分我已经充分理解了,这要感谢 egregs 对另一个问题的解释)。
这是我的宏定义:
\newcommand{\braket}[2][\middle]{\ensuremath{
\begingroup
\begingroup\lccode`~=`<
\lowercase{\endgroup\def~}{#1\langle}
\begingroup\lccode`~=`|
\lowercase{\endgroup\def~}{#1\pipedel}
\begingroup\lccode`~=`>
\lowercase{\endgroup\def~}{#1\rangle}
\edef\pipedel{\delimiter\the\delcode`|}
\mathchardef\lt\mathcode`<
\mathchardef\pipechar\mathcode`|
\mathchardef\gt\mathcode`>
\mathcode`\<=\string"8000
\mathcode`\|=\string"8000
\mathcode`\>=\string"8000
\left.
#2
\right.
\endgroup
}}
以下用法均按预期工作:
\braket{<\psi|\psi>}
\braket{<\psi|A|\psi>}
\braket{<\psi|\frac{p^2}{2m}|\psi>}
\braket[\Big]{<\alpha|\beta>}
\braket{|a \gt 0>}
\braket[]{<\psi|\frac{p^2}{2m}|\phi>}
(最后一个只是禁用自动尺寸适应)。
然而,以下不是正常工作:
\braket{<0|1>}
它应该给出“〈0|1〉”但只给出“〈0〉”。
那么我的宏有什么问题?我该如何修复它?
答案1
问题是,当 TeX 找到活动管道时,它会将其扩展为
\delimiter 2532108
并且其后的数字将并入该代码中。
\mathchardef\lt\mathcode`<
\mathchardef\pipechar\mathcode`|
\mathchardef\gt\mathcode`>
\edef\pipedel{\delimiter\the\delcode`| }
\show\pipedel
\newcommand{\braket}[2][\middle]{
\begingroup
\begingroup\lccode`~=`<
\lowercase{\endgroup\def~}{#1\langle}
\begingroup\lccode`~=`|
\lowercase{\endgroup\def~}{#1\pipedel\relax}
\begingroup\lccode`~=`>
\lowercase{\endgroup\def~}{#1\rangle}
\mathcode`\<=\string"8000
\mathcode`\|=\string"8000
\mathcode`\>=\string"8000
\mathopen{}\left.#2\right.\mathclose{}
\endgroup
}
这\relax
将避免这个问题。另外有些部分在定义之外会更好,因此\ensuremath
不建议使用。
注意\lowercase
诀窍
当一个字符(类别代码 11 或 12)被分配了数学代码"8000
并且在数学模式下被发现时,TeX 会将其视为活动的(即像宏一样),并且需要将其定义为活动字符。
一个很常用的技巧就是利用这一点~
是主动;当我们想赋予主动意义时<
,有两种策略。第一种是
{\catcode`<=\active \gdef<{something}}
这有一些缺点:我们被迫提前执行它,而且全球的所以我们采用不同的策略:
\begingroup\lccode`~=`< \lowercase{\endgroup\def~}{something}
这是如何工作的?首先,我们打开一个组,并在该组中告诉 TeX 的小写对应项~
是<
。然后我们执行\lowercase
,这会将字符标记转换为小写字母(但控制序列保持不变),并将标记放回原处,就像它们从一开始就在那里一样。因此 TeX 认为
\endgroup\def<{something}
(但<
是激活,因为\lowercase
不会改变类别代码)。取消和\endgroup
之间的对应关系,并执行定义。 稍后,我们说,魔法会发生(是预防~
<
\mathcode`<=\string"8000
\string
巴别塔这可能会成为"
一个活跃的角色)。