\mathpalette 的奥秘

\mathpalette 的奥秘

我想制作一个宏,\vfrac其输出如下所示:

$$\displaylines{
  \displaystyle\raise.25ex\hbox{$\displaystyle1$}\!/\!\lower.5ex\hbox{$\displaystyle2$} \cr
  \textstyle\raise.25ex\hbox{$\textstyle1$}\!/\!\lower.5ex\hbox{$\textstyle2$}\cr
  \scriptstyle\raise.25ex\hbox{$\scriptstyle1$}\!/\!\lower.5ex\hbox{$\scriptstyle2$}\cr
  \scriptscriptstyle\raise.25ex\hbox{$\scriptscriptstyle1$}\!/\!\lower.5ex\hbox{$\scriptscriptstyle2$}\cr
}$$

在此处输入图片描述

我使用纯格式,因此我尝试遵循 TeXbook 附录 B:

\catcode`@=11
\def\vfrac#1#2{\mathpalette\vfr@c{#1}{#2}}
\def\vfr@c#1#2{\raise.5ex\hbox{$#1$}/\lower.25ex\hbox{$#2$}}
\catcode`@=12
$\vfrac{1}{2} \quad {}^{\vfrac12}$

看起来像

在此处输入图片描述

这是什么我甚至不知道……

哦,等等,它似乎将“1”作为第二个参数。通过 tex.sx 快速搜索,我得到了亨德里克的问题,其中他只是给 提供了一个空的第一个参数\mathpalette。但是,当我在上面的宏中尝试这样做时,我得到了一个错误! Argument of \vfr@c has an extra }.

我很困惑。如何\mathpalette工作?

答案1

\mathpalette在许多必须将类似的标记列表传递给的情况下非常方便\mathchoice,也就是说,我们想要扩展形式

\mathchoice
  {<something in \displaystyle>}
  {<something in \textstyle>}
  {<something in \scriptstyle>}
  {<something in \scriptscriptstyle>}

但是,为了实现最大的灵活性, 的第一个参数必须\mathpalette是双参数宏,其第一个参数是数学样式声明。让我们看一个例子, 的 Plain TeX 定义\in

\def\notin{\mathrel{\mathpalette\c@ncel\in}}

接下来是

\def\c@ncel#1#2{\m@th\ooalign{$\hfil#1\mkern1mu/\hfil$\crcr$#1#2$}}

不要看 的复杂性,\c@ncel而要看第一个参数确实必须是样式声明。如果 TeX 发现 ,\notin它会执行\mathrel{\mathpalette\c@ncel\in},并且里面的子公式\mathrel会扩展为

\mathchoice
  {\c@ncel\displaystyle{\in}}%
  {\c@ncel\textstyle{\in}}%
  {\c@ncel\scriptstyle{\in}}%
  {\c@ncel\scriptscriptstyle{\in}}

因此,在文本样式中要排版的数学列表将\c@ncel\textstyle{\in}

\m@th\ooalign{$\hfil\textstyle\mkern1mu/\hfil$\crcr$\textstyle\in$}

\ooalign是允许叠加字符的技巧(很简单\halign,但基线跳跃被抑制)。效果是将稍微偏移的条叠加到\in

的调用\mathpalette也可以是这种形式\def\xyz{\mathpalette\XYZ},在这种情况下,宏\xyz似乎会接受一个参数,而这实际上是 \XYZ 的第二个参数。这就是宏以这种方式定义的原因。

您的\vfrac宏可以通过 来定义\mathpalette,因为结构相同;但是必须在调用之前收集两个参数\mathpalette并将其存储在某些宏中:

\catcode`@=11
\def\vfrac#1#2{\def\vf@num{#1}\def\vf@den{#2}\mathpalette\vfr@c\relax}
\def\vfr@c#1#2{%
  \raise.5ex\hbox{$\m@th#1\vf@num$}\!/\!\lower.25ex\hbox{$\m@th#1\vf@den$}}
\catcode`@=12

(正如 Aditya 所观察到的,\m@th在这些情况下应该始终被调用。)这里我们不需要的第二个参数\vfr@c,但无论如何它必须存在;可以使用\relax{},它们是相同的:第二个参数永远不会被使用。

答案2

\mathpalette定义为

\def\mathpalette#1#2{%
  \mathchoice
    {#1\displaystyle{#2}}%
    {#1\textstyle{#2}}%
    {#1\scriptstyle{#2}}%
    {#1\scriptscriptstyle{#2}}}

因此需要两个参数。第一个参数按 选择的相应样式按原样排版\mathchoice,而第二个参数则使用强制样式排版。

宏的基本性质\vfrac,足以\relax作为第一个#1或第二个#2参数提供\mathpalette


\mathchoice更好的选择可能是直接在您的定义中使用\vfrac

$$\displaylines{
  \displaystyle\raise.25ex\hbox{$\displaystyle1$}\!/\!\lower.5ex\hbox{$\displaystyle2$} \cr
  \textstyle\raise.25ex\hbox{$\textstyle1$}\!/\!\lower.5ex\hbox{$\textstyle2$}\cr
  \scriptstyle\raise.25ex\hbox{$\scriptstyle1$}\!/\!\lower.5ex\hbox{$\scriptstyle2$}\cr
  \scriptscriptstyle\raise.25ex\hbox{$\scriptscriptstyle1$}\!/\!\lower.5ex\hbox{$\scriptscriptstyle2$}\cr
}$$

\def\vfrac#1#2{%
  \mathchoice%
    {\raise.5ex\hbox{$\displaystyle#1$}/\lower.25ex\hbox{$\displaystyle#2$}}% \displaystyle
    {\raise.5ex\hbox{$\textstyle#1$}/\lower.25ex\hbox{$\textstyle#2$}}% \textstyle
    {\raise.5ex\hbox{$\scriptstyle#1$}/\lower.25ex\hbox{$\scriptstyle#2$}}% \scriptstyle
    {\raise.5ex\hbox{$\scriptscriptstyle#1$}/\lower.25ex\hbox{$\scriptscriptstyle#2$}}% \scriptscriptstyle
}%

$\vfrac{1}{2} \quad {}^{\vfrac12}$

在此处输入图片描述

您可能需要根据您的用途更改\raise\lower数量以匹配\displaylines。此外,现在您只剩下一个宏了!

相关内容