我想制作一个宏,\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
。此外,现在您只剩下一个宏了!