(Opinions needed) Likely upcoming changes to math mode precedence

I think one example is that both sin(x) and sin x are valid notation and common to use, and so a function doesn’t seem to be quite right, at least not if we want to allow the markup to mimic the math notation closely.

I see. But then my next question: Why is op not a Typst function, while math.abs is? (And if it is, why isn’t sin then, which is a special case of op?
With other words, why don’t we implement op as a Typst function and circumvent the problems with that?

op is a Typst function that you can use to make operators like sin:

#let mysin = math.op("sin")
$ mysin(x) $

image

Here mysin(x) is not a function call, it’s the value mysin followed by (x). But the value mysin was obtained by calling op. You could also write

$ op("sin")(x) $

and get the same result.

3 Likes

You can already partially do this by sacrificing one of the symbol accents that works as a function already:

#let sin = sym.circle
#show sin: math.sin
#let accent-char = sin([]).accent
#show math.accent.where(accent: accent-char): it => {
  math.sin + $(it.base)$
}

These now render the same,
but the first line is an actual function call.
$ sin(x) \
  sin (x)
$
2 Likes

I would also vote for option B for consistency with other similar cases such as x^-1 which is rendered as x^(-) 1. See also the related issue: Raising to the power of a negative number should not require parenthesis · Issue #5722 · typst/typst · GitHub

Thanks @Y.D.X for the visual summary.

Just to clarify as the case with f_i (x) shows no representation on the “Next version” side: I guess this pattern will still be supported by the next version and render the same?

this pattern will still be supported

Yes; I omit it because I think f_i (x) will become rare in the next version. Just likef (x) today, which I believe most people would write f(x) instead.

1 Like

Just a data point. I was also hit by this today as I was translating my brother’s thesis from LaTeX to Typst.

$
"CF"(X, k)  &= limits(sum)_(x in X) I_k(x) & quad "Class frequency"          \
$

screenshot_2025-07-14_20:03:23

I would thus also be in support for option B.

1 Like

I’m not a mathematician so I could be wrong, but I support option C or D for the following reasons:

  1. Symbols of functions, like f, can be standalone. I mean, when we say there is a function, we don’t have to say f(x). In this case, f is math symbol. And f(x) is a kind of operation to map x to something else via function f. In most cases, attachments are symbols, not operations. Because of this, when we write $f_i(x)$, we would not expect i(x) to be something attached, unless i is a user-defined “programming” function (stated as below). In this case, treating the i(x) part as the attachment seems to be strange.

  2. Some special functions, like “sin”, they are predefined symbols, although it could be rare to see “sin”, “cos”, etc., alone.

  3. However, abs(x) represents “|x|” in math. Thus, “abs” itself is not a symbol; instead, “abs(x)” the whole thing is. Because abs is a programming function, not a mathematical symbol or operation. A standalone abs does not make mathematical sense.

  4. For other user-defined functions, I think they would probably prefer keep the whole thing together. As an example, I defined a function to show conditional expectation, like

     #let Exp(x, ..args) = $E lr((#x mid(|) #args.pos().join(",")))$ 
    

    When I write $e^Exp(x,u)$, I definitely want the part like $E(x|u)$ to show at the corner, instead of a “E” at the corner but “(x|u)” not.

    Another example is the Imaginary number. If we define a function

     #let Im(a,b) = $#a + #b i$
    

    then I also expect $e^Im(1,2)$ to show something like “e^(1+2i)”, not “e^1 + 2i”.

Overall, I think it would be better to act differently for different components. If the attached component is a “programming” function, like abs and user-defined functions, treat the whole thing as the attachment. For math.op and normal math symbols, don’t show them like function calls.

2 Likes

I don’t know if it makes a difference for your argument, but from $e^Exp(x,u)$ you’d get “e^Exp” followed by “(x, u)”, not “e^E” followed by “(x|u)”; for $e^Im(1,2)$ you’d get “e^Im” followed by “(1,2)”, not “e^1” followed by “+ 2i”.

In other words, the issue isn’t that the function is evaluated and only part of the result becomes the superscript; it’s that option B would not call the function, and put the parameters outside the superscript.

1 Like