# Mixing math character classes (e.g. \mathord to the left and \mathrel to the right)

It is possible to have a symbol or group behave to the left as if it had one particular math character class and to the right as if it had another?

One typical case where this comes up is when one parenthesizes part of a longer expression. For example, enclosing the first part of $$U \rightarrow U \rightarrow U$$ in square brackets ($$[U \rightarrow] U \rightarrow U$$) will lead to the closing square bracket ] being too close to the following U. In this case, creating a new \mathrel out of the arrow and the closing square bracket ($$[U \mathrel{\rightarrow ]} U \rightarrow U$$) solves the problem:

but a fully general solution would be nice.

Another example: Perhaps I would like to define an asymmetric relation symbol 🍂 (a leaf, whatever this might stand for) for which I would like to make it visually clear that it conceptually binds closer to its right-hand argument than to the left. The result should look like this: M 🍂v. Unlike the title of this question, this one would actually be "\mathord to the right and \mathrel to the left". (Perhaps this is a two-argument function that accepts a matrix and a vector. The assumption is that there is a good reason for using infix notation and for writing it closer to the vector. Maybe it transforms the vector before multiplying the vector to the matrix, in a way that the vector transformation makes only sense if combined with matrix multiplication. Note that I've picked such an example for visual clarity, but pairing \mathord up with \mathbin instead of \mathrel might be more realistic.)

Perhaps a better example: I might define a typecast operator for some formal language. I'd like to denote the typecast expression as expr ∽τ (using \backsim), with type τ set closer to the symbol ∽: it's as if ∽ first merged with the target type to then form a left-unary typecast operator; we can even enumerate all such operators ∽τ under the assumption that the number of possible target types τ is small.

The hacky solution to do a lot of hierarchical math character class assignment (i.e. $$M \mathrel{\mathord{\someleafsymbol} v}$$ for my first leaf example) is dispreferred. I was thinking of a macro \DeclareTwofaceMathchar{lclass}{rclass}{symbol} where lclass and rclass are among \mathord, \mathop, \mathbin, ...

If there is no such fully general solution, an explanation for why there is none will also be a good answer.

Somewhat related is my Addendum about a "genuine unary plus" at the bottom of this question: What is a good method for producing a unary plus/minus sign that always works?

With some juggling of the different math classes it's possible to achieve what you want:

\documentclass{article}
\newcommand*\mixedmath[3]{%
#1{#3}%
\ifx#1\mathbin
\nonscript\mskip-\medmuskip
\mathord{}%
\fi
\ifx#1\mathpunct
\nonscript\mskip-\thinmuskip
\fi
\mathclose{}\mathopen{}%
\ifx#2\mathbin
\mathord{}%
\nonscript\mskip-\medmuskip
\fi
#2{}%
}
\newcommand*\ordrel[1]{\mixedmath{\mathord}{\mathrel}{#1}}
\begin{document}
\verb|ord-rel|: $A \ordrel{\vee} B$

\verb|bin-bin|: $A \mixedmath{\mathbin}{\mathbin}{\vee} B$

\verb|bin-rel|: $A \mixedmath{\mathbin}{\mathrel}{\vee} B$

\verb|rel-bin|: $A \mixedmath{\mathrel}{\mathbin}{\vee} B$
\end{document}

\documentclass{article}
\newcommand*\ordrel[1]{\mathord{#1}\mskip-\thickmuskip\mathrel{}}
\begin{document}
$A \ordrel{\vee} B$
\end{document}


Here's the idea of the \mixedmath command: the first argument is the "left behavior", the second one the "right behavior" and the third one the character(s) to be used.

The character is set with the "left" math class, followed by \mathclose{}. I chose \mathclose since this only adds some space if it follows \mathbin (in which case it changes the \mathbin to \mathord) or \mathpunct. The first two \ifx's take care of those two cases. After the \mathclose{} I put \mathopen{} (no space according to the table!), followed by the "right" math class. Due to the \mathopen, I only have to give the \mathbin case a special treatment, which is done in the last \ifx.

The \nonscript is needed in each case since you don't have to put the negative spaces in \script(script)style. (This is what the parentheses in the table in David's answer mean; in those cases, the space is only added in \displaystyle and in \textstyle!)

• Very clever manipulation of the rules! Also, I learned a new primitive (\nonscript). – Ryan Reich May 4 '13 at 4:00
• @Ryan: egreg taught me :-) – Hendrik Vogt May 4 '13 at 5:49
• @Hendrik Vogt: Hi, the code from this answer has been very helpful and I have been using it in my work. Would you be willing to grant me a license to the code posted in this answer under the current LPPL (or even any compatible permissive license such as CC0)? I would like to put it in my personal LaTeX package where I collect math-mode snippets that I found useful. Since that package already contains code copied and modified from other existing packages it should be under LPPL so that I can legally "redistribute" (i.e., share with a handful of coauthors) it as one package. – wea0 Sep 14 '17 at 23:32

There is no solution in general as the space that is added between each adjacent math class is fixed in TeX (luatex allows it to be changed)

For any given expression, rather than deeply nested \math... commands you can simply add the space that TeX would have added had the class been different (which will be \thinmuskip, \medmuskip or \thickmuskip).

The matrix of spaces added is in the TeXBook but there is a version in texbytopic page 205

latex defines \, \> and \; to add thin medium and thick space.

• @LoverofStructure you should have more faith:-) : from latex.ltx: \def\>{\mskip\medmuskip} \def\;{\mskip\thickmuskip} \def\!{\mskip-\thinmuskip} – David Carlisle May 1 '13 at 16:28
• @LoverofStructure there is also \let\:=\> :-) – David Carlisle May 1 '13 at 16:28
• ltmath.dtd says % \: Nickname for the medium space since |\>| is not available inside tabbing – David Carlisle May 1 '13 at 16:30
• Morten Høgholm discussed this in his Bachelor thesis, p. 15. – Svend Tveskæg May 2 '13 at 8:28
• It seems that there are some errors in your table: in the "Close" and "Punct" columns, there should only be a * for "Bin", not for "Rel". – Hendrik Vogt May 2 '13 at 9:03