I've been playing around with unicode mathematics input. I noticed that both

\Umathchardef\plus = 2 0 "002B


\Umathcode "002B = 2 0 "002B

lead to the same behavior of \plus in math mode (assuming that a suitable math font has been assigned to family 0).

What are the advantages/disadvantages, if any, of one method or the other to define a control sequence to use in mathematics input?

  • 1
    The main difference is that you can use \let\plus=+ in textmode as well. Commented Dec 16, 2019 at 4:33

4 Answers 4


First, there is performance: \Umathchardef will be slightly faster (there is less indirection after all), but that shouldn't be relevant in most cases.

On the other hand, setting the \Umathcode for + first and then using \let to define your symbol also sets the right \Umathcode for +, so you can also use + directly. Of course, even if you use \Umathchardef you can still assign the \Umathcode, but then they are not connected: If someone changes the \Umathcode for +, the command \plus defined as \let\plus=+ changes too, but \Umathchardef has to be changed separately. This is especially important in e.g. unicode-math which changes mathcodes a lot.

Also, they behave differently outside of math mode: For XeTeX, a command defined by \Umathchardef always yields an error outside of math mode. (In LuaTeX, it will insert the corresponding character from the text font.) While the \let based command always inserts the character the command was \let to in text mode. What is better again depends on the character: For \sum, there is no point in allowing it outside of math mode, so it should create an error there. On the other hand for \alpha, you might want the name to also allow inserting the greek character in text mode. In that case you could for example do

\Umathcode"03B1=2 0 "1D6FC

then your math \alpha is italic math alpha 𝛼, while your text mode \alpha is still a regular text Ξ±.

So \Umathchardef is a bit faster, has better error handling in XeTeX and doesn't introduce hidden dependencies on the mathcode of some character, but \Umathcode and \let are more flexible and might be shorter if you set the \Umathcode anyway.


hyperref won't like it if you \let a command to a char. It is tricky to detect such commands and the hyperref code currently can't do it (this will perhaps change but not directly). There are a number of bug reports at the hyperref and unicode-math github about this, e.g. https://github.com/latex3/hyperref/issues/63 and https://github.com/wspr/unicode-math/issues/532. Instead of using \let it is better to use \def (\newcommand).

In the bookmarks you will see differences too. The \Umathchardef variant is currently lost (this will perhaps change too but also not directly).


\Umathchardef\plusmathchar = 2 0 "002B

\Umathcode "002B = 2 0 "002B

\Umathcode "002B = 2 0 "002B

$a$ % initialize math fonts

text: M \plusmathchar\ L \pluslet\ D  \plusdef  %error with xelatex

math: $ M \plusmathchar L \pluslet D \plusdef  $

\section{mathchar text X \plusmathchar\ Y} % error with xelatex
\section{mathchar math X $\plusmathchar$ Y}

%\section{let text X \pluslet\ Y} %lots of errors with hyperref
%\section{let math X $\pluslet$ Y}%lots of errors with hyperref 

\section{def text X \plusdef\ Y}
\section{def math X $\plusdef$ Y}


output with lualatex

Compiled without hyperref and with the commented part:

enter image description here


enter image description here

  • The upcoming text module does handle all implicit chars properly, so we should be fine to handle this in hyperref (or ...)
    – Joseph Wright
    Commented Dec 17, 2019 at 9:50
  • @JosephWright I did write "this will perhaps change" for a reason ;-). Commented Dec 17, 2019 at 9:52

We can check the difference of these two assignments in the log:

\Umathchardef\plus = 2 0 "002B

\Umathcode "002B = 2 0 "002B
> \plus=\Umathchar"2"00"00002B.
l.2 \show\plus

> \plus=the character +.
l.6 \show\plus


The fundamental difference is that with \Umathchardef\plus you get a token that represents this particular math symbol in the output, whereas with \let\plus=+ you make an alias for the + character in the input.

Another problem with the second variant is that it is non-local, i.e. the assignment of the mathcode and the definition of the control sequence do not take place in the same statement.

Also, the first statement is how it is meant to be doneβ„’. From the TeXbook:

A~hundred or so definitions like
\def\sum{\mathchar"1350 }
would therefore suffice to define the special symbols of plain \TeX\null. But
there is a better way: \TeX\ has a primitive command ^|\mathchardef|,
which relates to |\mathchar| just as ^|\chardef| does to |\char|.
Appendix~B has a hundred or so definitions like
to define the special symbols.
  • Bonus question about the TeXbook snippet: Why does Knuth use \TeX\null. instead of just \TeX.? If you want to answer, please do so in the chat. Commented Dec 16, 2019 at 4:42
  • 1
    The period should be considered as a sentence ending period. After \null, the space factor is set to 1000, so the period makes it 3000. Without the \null, the space factor would be 999 (because \TeX ends with X), so the period would not be considered as sentence ending. The LaTeX version of \TeX ends with \@.
    – egreg
    Commented Dec 16, 2019 at 9:26

unicode-math uses the second approach for almost all symbols, as you can check (see Henri Menke's answer):


$\meaning\Bbbzero$, $\meaning\equiv$


enter image description here

So if you use Lua- or XeLaTeX the work is already done and you do not need to do it by hand. The best argument for this approach is that your code will be much more readable by avoiding many macros. Compare:

$βˆ«β‚€ΒΉ xΒ³ \, dx$ - $\int_0^1 x^3 \, dx$, $dΒ²rΒ²/d\vec rΒ² = 2πŸ™$ - $d^2 r^2 / d\vec r^2 =2\Bbbone$

As you try out the \Umath... commands I think that you consider unsing Plain Lua/XeTeX. In this case you have to do (or correct) it by hand as Lua- and XeTeX set the following \Umathcodes:

For letters: \Umathcode`<char> = 7 1 `<char>,
for numbers: \Umathcode`<char> = 7 0 `<char>,
else:        \Umathcode`<char> = 0 0 `<char>.

Then you have to write many lines for all the symbold you need. I did this some time ago as I like PlainTex. Here are some examples (my math font is in \fam1):

\Umathcode`∞="0"1`∞     \let\infty=∞
\Umathcode`𝟜="0"1`𝟜    \let\Bbbfour=𝟜
\Umathcode`∏="1"1`∏     \let\prod=∏
\Umathcode`βˆ“="2"1`βˆ“     \let\mp=βˆ“
\Umathcode`β†—="3"1`β†—     \let\nearrow=β†—

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .