(Opinions needed) Likely upcoming changes to math mode precedence

@ian I have read through your post a few times now, and also read through mine again, and collected my thoughts.


With most of your points, I think they do have something to it, but I also want to push back a little on them. Let me unpack my thoughts:

Option B hides typesetting affordances

It is true that there are still differences between mathematical functions and Typst functions, primarily in how you can interact with them. That said, I have problems with the framing that option B is harmful in this regard. The fact that mathematical functions and typesetting functions work different in some regards does not make it worse for them to also work the same in other regards, or else we’d have to try to make them as different as possible.

Even if the two types of functions still work differently in some ways, I think
the predictability of how they interact with attachments is good to have.

Option B breaks trust in composability

With this argument, I’m conflicted. I see your point, but at the same time I also don’t really buy it. It essentially implies that just because function calls have highest precedence in most contexts, they must have maximum precedence everywhere. I think the same argument could be made for attachments: Why would an attachment compose differently with a function than with a symbol? To an extent, that also breaks trust in how a Typst attachment composes with other syntax. As a user, I could be left wondering why #let ff(x) = $bb(f)(#x)$ composes differently with my attachments than #let ff = $bb(f)$.

I guess the reason I’m conflicted is the following: Yes, at the surface option B does break composability a bit, but so does option C, just in another way. If you go a bit deeper, neither does break composability particularly badly because in both cases you can compose, you just have to know the rules of composition. But for option B, the rule is much more obvious! The rule to add parentheses and when you need them is a simple one; it’s a rule that you can understand as a beginner without learning about what runtime and types even are.

Meanwhile, the rule of how runtime-parsed attachments compose is much harder to understand, as it requires context that is not only syntactically invisible to the compiler, but also obtuse to many beginners.

Laurenz also makes an argument about syntax highlighting for math under option B that I have some concerns with

This breaks down when you have false positives, or expressions with the identifier(…) syntax that aren’t functions, such as implied multiplication.

While I agree that syntax highlighting unfortunately doesn’t tell the full story about an equation with option B either, I want to clarify that the part of my argument that you quoted was exclusive about precedence, i.e. the fact that you can understand precedence purely based on syntax highlighting. You still cannot fully understand the mathemtical role a piece of syntax plays purely based on highlighting. Semantic highlighting would improve that (though also to an extent; for some things we just don’t have enough information generally).

However, I would argue that semantic highlighting and runtime parsing are separate concerns. (1) Semantic highlighting can improve highlighting in some scenarios regardless of option B or C. (2) Semantic highlighting can fix the issue that purely syntactical highlighting does not let you reason about precedence in option C. But that doesn’t change the fact that runtime parsing introduces the issue in the first place, while option B does not.

There are also a lot of places where runtime highlighting is not available or would complicate highlighting a lot (e.g. if we want semantic highlighting in docs or a blog post, that would now need full-blown compilation instead of just typst_syntax). For purely syntactical highlighting cases, option C is strictly worse. It’s perhaps not the end of the world, but basic non-semantic highlighting would just be a bit less useful with runtime parsing, so there is a small downside here.

I think the point of highlighting Typst math isn’t to make the meaning of the mathematics clearer. The point of syntax highlighting is to make the meaning of the Typst source code clearer.

Precisely! I only wanted to argue that it makes precedence clearer (which is a Typst concern, not a mathematical one).

I don’t think there’s any reasonable subset of Typst’s math syntax that wouldn’t either require the use of a substantial amount of the Typst compiler or would be something that isn’t actually Typst.

I tend to agree that this is a larger problem with repurposing Typst’s math syntax outside of Typst than the runtime stuff. So I’m fine with leaving that argument off the table and considering only what’s best for Typst.

I think this is a fair point, but I disagree with it because I consider Typst’s normal context of use. The main way that most people write Typst is with a live, incremental update of the document in a different pane of their editor.

While I think there is a fair argument here, I do think it misses one important point. A crucial question, in my view, is why something is more readable in the first place. I’d argue that it’s typically the case because it’s more intuitive or easier to build an understanding for. Of course, I can check how it renders easily, but if I check every time without building a deeper understanding, I will never be able to write it correctly in the first place. And, on top, even if I have understood how it works, when using a custom definition, I will need to know how it was defined to know a thing as basic as what the precedence of it is.

I think that’s the main benefit of optimizing for readability rather than how many letters per second you can actually read as a power user. That’s why I don’t really buy into the “optimize for writability over readability” argument.


As a more structured response, let me recap my point on each of yours:

  • Two harms of option B for new users
    • Option B hides typesetting affordances: I agree that the distinction between math and Typst functions is still relevant, but I disagree that Option B makes this worse.
    • Option B breaks trust in composability: I agree that it hurts composability of functions a bit (though I think “breaks trust” is a bit overly strong of a statement). My counterpoint is though that option C composes less predictably which is also important.
  • What is Syntax Highlighting For: I agree that option B isn’t the holy grail syntax highlighting wise, but I would say it is strictly better than option C, even if not by much.
  • The Downsides of Runtime Math Parsing
    • Runtime math parsing doesn’t really change the status quo: Accepted
  • Human Readability vs. Human Writability: I disagree because the core issue is not literally “reading”, but building an understanding.

I see that runtime parsing has upsides. It gives the good attachment behaviour for symbols, while avoiding additional parentheses in the function case. To an extent, I also agree with the reasoning that functions feel a bit more composable.

But the big concern I still feel is about predictability. Not only would it be hard for a beginner to build a mental model for the precedence of attachments (as they first need to understand the different kinds of data types at play); even as a seasoned user, you cannot predict the precedence of an attachment by just looking at the source. While you argue that instant preview alleviates this problem, for me the syntactical structure of an equation is such a basic concern that it needs to be clear just from the markup. (Perhaps, this is just a matter of philosophy.) On top, I fear that regardless of other differences between Typst and math functions the behaviour of the middle ground between symbols and functions (e.g. sin) will remain unintuitive even for advanced users.

There is also the point about syntax highlighting and of course also the complexity that runtime parsing introduces. But compared to my concerns with predictability, these are honestly minor.

In the end, I remain unconvinced that saving these extra parentheses is worth making precedence so much more intricate to reason about. I also think that we’ve held back on a change here for about as long as possible. Really, this should have been reverted a long time ago as the status quo is so clearly worse than either option B or C.

It is clear that you are very passionate about this topic and have put a ton of effort into the post and especially also the PR (which looks very well done), but in the end I still believe that option B is the better choice for Typst. I hope I’ve made understandable why even if you disagree.

7 Likes