# The mysteries of \mathpalette

I would like to make a macro, \vfrac, which output would look like:

$$\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 }$$


I use the plain-format, so I tried to follow the TeXbook Appendix 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}$


which looks like

What is this I don't even...

Oh wait, it looks like it's taking the "1" as the second argument. A quick search through tex.sx gives me Hendrik's question, where he just gives an empty first argument to \mathpalette. However, when I try that in my above macro, I get an error ! Argument of \vfr@c has an extra }.

I'm at loss. How does \mathpalette work?

• Does defining \vfrac using \def\vfrac#1#2{\mathpalette\relax{\vfr@c{#1}{#2}}} or \def\vfrac#1#2{\mathpalette{\vfr@c{#1}{#2}}\relax} solve your problem?
– Werner
Nov 10, 2011 at 19:15
• @Werner: it fixed the correct reading of arguments, but the \hbox contents do not get the correct size (now that I think about it, how could they). I should somehow be able to put the first argument to \mathpalette as an argument to \vr@c I think. Nov 10, 2011 at 19:19

\mathpalette comes very handy in many situations where similar token lists must be passed to \mathchoice, that is, we want an expansion of the form

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


However, to allow for maximum flexibility, the first argument to \mathpalette must be a two-argument macro, whose first argument is a math style declaration. Let's see an example, Plain TeX definition of \in:

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


This is followed by

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


Don't look at the complications of \c@ncel but at the fact that the first argument must indeed be a style declaration. If TeX finds \notin it will do \mathrel{\mathpalette\c@ncel\in}, and the subformula inside \mathrel is expanded into

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


so, in text style the math list to typeset will be \c@ncel\textstyle{\in}, that is

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


Here \ooalign is the trick that allows for superimposing characters (it's a simple \halign but baseline skip is suppressed). The effect is of superimposing a slighly offset bar to \in.

The call of \mathpalette can also be of the form \def\xyz{\mathpalette\XYZ} and in this case the macro \xyz will appear to take an argument, which will actually be the second argument for \XYZ. And this is why the macro is defined this way.

Your \vfrac macro can be defined via \mathpalette, since the structure is the same; but the two arguments must be gathered before calling \mathpalette and stored in some macros:

\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


(As Aditya observes, \m@th should always be called in these cases.) Here we don't need the second argument for \vfr@c, but it must be there anyway; one can use \relax or {}, it's the same: that second argument will never be used.

• Ah, ofcourse! I was so stuck at thinking how to transport the parameters "as is" to the helper macro, it didn't even occur to me you could just \def them. Thanks! Nov 11, 2011 at 4:43
• The two arguments can also be packed in {{#1}{#2}} and retrieved using \@car \@cdr or \@first/secondoftwo if definitions are to be avoided. Sep 21, 2021 at 13:47

\mathpalette is defined as

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


and therefore takes two arguments. The first argument is typeset as-is in the respective style as chosen by \mathchoice, while the second argument is typeset with a forced style.

The elementary nature of your \vfrac macro, it suffices to supply \relax as the first #1 or second #2 argument to \mathpalette.

A better choice might be to use \mathchoice directly in your definition of \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}$


You may have to change the \raise and \lower quantities to match that in your \displaylines depending on your usage. Moreover, now you're down to one macro!

• That's nice, thanks, but every time I find myself writing the exact same thing more than once, I get the feeling I'm doing something wrong. Nov 10, 2011 at 19:49
• You should set \mathsurround to 0 to avoid extra spacing around math. Usually this is done by using \hbox{\m@th$...$} Nov 10, 2011 at 20:19
• @morbusg: That's true. But it's better that such coding is hidden from view in a macro that it clutter the readability within the general document.
– Werner
Nov 10, 2011 at 20:28
• The explicit \mathchoice approach is definitely the way to go in case I need to make small adjustments to each style level. Thanks again! Nov 11, 2011 at 4:46