4

I like to define macros for my binary relations, say: \newcommand{\pref}{\mathrel{R}}. I use it as: a \pref b. But I also sometimes want to consider my binary relation as a function, thus, for example, write \pref(A) or \pref = \pref', or to consider it as a set of pairs and write \foreach (a, b) \in \pref: ….

The spacing should change according to the case at hand, and it seems possible to detect the right case automatically, at least, in most cases. I am ok to fix the remaining cases manually but an automatic solution for the common cases would be nice. For example, when an open parenthesis follows \pref it should cease to be a \mathrel and become (I suppose) a \mathord.

Relatedly, I wonder how to change the category manually while still using my macro pref, when required (assuming it can’t be done automatically)? I understand that I could define the macro with no qualifier: \newcommand{\pref}{R} then use it by qualifying it systematically when necessary (\mathrel{\pref}, for example), but I’d rather have \mathrel as a default and override it when necessary, if possible.

  • {\pref} would do – egreg Oct 24 '18 at 16:10
  • Relation symbols already act according to the context; if they're next to another relation symbol, no space is inserted between them (and no penalty either); otherwise a thick space is inserted. – egreg Oct 24 '18 at 17:28
  • @egreg Where can I find some documentation about the spacing applied when using {\pref} or how it adjusts according to context? (I like to know how I am supposed to use the commands rather than find it out by trial and error, which becomes impractical when many combinations are possible, and I couldn’t find this explained in ams doc or Lamport’s book.) – Olivier Cailloux Oct 24 '18 at 18:36
  • {<math material>} makes a subformula that's in its entirety treated as an ordinary symbol. – egreg Oct 24 '18 at 20:00
  • @egreg I am surprised that I have never seen this question discussed anywhere. It seems to me like a pretty common thing in mathematics (e.g. set theory, decision theory) to want to treat a symbol as a relation or a non-relation depending on context. How do authors deal with this problem according to your experience? Nothing better than systematical use of {<math>}? – Olivier Cailloux Oct 25 '18 at 09:23

1 Answers1

4

I'm afraid your problem can't be solved (at least in legacy TeX implementations, maybe LuaTeX can do something about it).

A relation symbol (defined with \mathchardef and given class 3), a simple character (given class 3 through its \mathcode), a symbol in a different class but preceded by \mathrel or finally a subformula in the reach of \mathrel (that is, \mathrel{<subformula>}), are marked as relation nodes in the math list that's being built.

When the formula ends, the math list is traversed from left to right and TeX builds boxes from nodes, also inserting spaces and penalties when needed.

For instance it will insert no space and no penalty between consecutive relation nodes, but a thick space between a different class node and a relation node according to the table

enter image description here

(see https://tex.stackexchange.com/a/81777/4427 for details).

Thus, if you do x\in\pref(A), there will be no space between \in and \pref and no space between \pref and (. But, as there's no “looking back”. There is just one “impossible” case in the 3 row and in the 3 column, that is, Rel-Bin or Bin-Rel, in which case the Bin node is made into an Ord one. The Rel nodes never change their class.

The “impossible cases” in the table are what makes binary operation nodes (class 2) become Ord nodes (so unary operators) in certain cases.

One would be tempted to use Bin nodes and change the size of \medmuskip to match \thickmuskip with something like

\newmuskip\savemedmuskip
\newcommand{\pref}{%
  \savemedmuskip=\medmuskip
  \medmuskip=\thickmuskip
  \mathbin R
  \medmuskip=\savemedmuskip
}

which was the (amended) proposal by Steven B. Segletes will not work, because TeX uses a single value for \medmuskip, precisely the one holding when the formula ends.

Steven's trick seems to work in an example, but just because his macro happens to do \medmuskip=\medmuskip instead of restoring a saved value.

Let's try

\documentclass{article}
\usepackage{amsmath}

\newmuskip\savemedmuskip
\newcommand{\pref}{%
  \savemedmuskip=\medmuskip
  \medmuskip=\thickmuskip
  \mathbin R
  \medmuskip=\savemedmuskip
}

\begin{document}

$a \mathrel R b$

$a \mathbin R b$

$a \pref b$

\end{document}

enter image description here

As you see, the second and third formulas are exactly the same.

If you want to change a Rel object into an Ord one, the only way is to brace it.

You could avoid braces by defining a *-variant:

\makeatletter
\newcommand{\pref}{\@ifstar{R}{\mathrel R}}
\makeatother

Example:

\documentclass{article}
\usepackage{amsmath}

\makeatletter
\newcommand{\pref}{\@ifstar{R}{\mathrel R}}
\makeatother

\begin{document}

$a \pref b$

$a \in \pref*(A)$

\end{document}

enter image description here

egreg
  • 1,121,712