[HN Gopher] Typst's Math Mode Problem
___________________________________________________________________
Typst's Math Mode Problem
Author : marcianx
Score : 103 points
Date : 2025-10-24 18:12 UTC (6 days ago)
(HTM) web link (laurmaedje.github.io)
(TXT) w3m dump (laurmaedje.github.io)
| TimorousBestie wrote:
| Having run into this bug/syntax ambiguity in my writing a lot, I
| don't find it's much of a bother. The typst engine runs fast
| enough that most of the time I can run a synced preview window,
| which makes this particular foible easy to catch.
| jeremyscanvic wrote:
| I've encountered this several times and even though I found it
| frustrating it didn't occur to me it could be something that
| could/should be fixed. You're always going to have some quirks if
| you want a syntax without too much parentheses right?
| MayeulC wrote:
| In LaTeX that would be close to option 2:
| e^{|x|} f_{i(x)}
|
| Except with {} for grouping, which I think is a good thing, as {}
| are never rendered, unlike parenthesis.
|
| I haven't used Typst much, so I am a bit wary of typesetting
| engines that are "too smart": It can be problematic when
| introducing new notations, which is quite common.
| fn-mote wrote:
| The post should lead with the proposed conclusion (revert and
| require explicit grouping) so that the reader can think about the
| arguments knowing the conclusion.
| weinzierl wrote:
| I had my gripes with LaTeX but the backslash in front of every
| macro was never one of them. I think it helps not only machine
| parsing but very much my human visual parsing.
|
| BTW one related trap in LaTeX is if a macro without parameters
| removes the trailing space from the output. The article mentions
| this in passing but does not say what Typst's solution is. Do
| Typst functions always require parentheses?
|
| I'm also confused about the following syntax and especially where
| the function ends: table.header([A], [B]) //
| This one is clear table.header()[A] // Makes sense,
| [A] turns magically into last param
| table.header()[A][B] // Slightly confusing, why would [B] also
| belong to the function? But OK. table.header()[A]
| [B] // Totally confusing, why is this an error now?
|
| For the last case: If it is a parameter list a space should not
| matter, if it is not [B] should not be part of the function and
| treated as unrelated.
| laurmaedje wrote:
| While not really related to the math topic, let me answer this:
|
| - You can add an arbitrary number of trailing `[..]` blocks and
| they are just trailing arguments. So 2 & 3 are really the same.
|
| - 3 & 4 are different because argument lists may _never_ have a
| space before them in Typst. you can also not write `calc.min
| (1, 2)`
|
| The reason why the space may not be added is that you can write
| #for x in range(5) [ Value is #x ]
|
| And `range(5) [..]` therefore needs to be different from
| `range(5)[..]`. This aligns with normal formatting conventions
| and I haven't seen this become a problem in practice.
| weinzierl wrote:
| Seeing it this way it makes sense. Thanks!
| xico wrote:
| Plus you can always `\catcode\[?]=0` if you really hate
| backslashes :-D
| nightskyblue wrote:
| When I found out that option B was already merged [1] I got very
| excited because the current behavior is still very unintuitive to
| me and one of the few areas where I prefer the behavior from
| Latex. Unfortunately, the changes were reverted shortly after
| because they discovered deeper issues with the new old design
| [2]. As far as I can see, there hasn't been any further progress
| on this, sadly.
|
| [1] https://github.com/typst/typst/pull/6442
|
| [2] https://github.com/typst/typst/pull/7084
| fweimer wrote:
| I find
| https://github.com/typst/typst/pull/7072#issuecomment-338580...
| more enlightening about what's going on. Specifically the
| difference between these three: 1/2(x + y)
| 1/x(x + y) 1/2^x(x + y)
|
| With a programming language background, that's just odd to
| reconcile. If 1/2 is treated as a rational integer literal,
| it's possible to explain the difference between the first two.
| (And apparently this difference is wildly expected, uncommon as
| fractions as literals are in programming languages.) But then
| the last one should turn into (1/2)x(x+y) because the
| exponentiation should not slip inside the literal. (I expect
| the different outcome in the comment is not the result of an
| algebraic simplification in his case. I really wish they had
| used 2/3 as the fraction to clarify this.)
|
| It seems that TeX users struggled with this at one point, too.
| That's why LaTeX users generally write $\frac{a}{b}$ instead of
| $a \over x$. Copious use of braces not rendered in the output
| certainly avoids precedence issues.
| MayeulC wrote:
| It's also a cultural thing I suppose, as I would personally
| understand all these expressions having just one as the
| numerator and the rest below.
|
| It may be related to the fact that "mixed numbers" were never
| part of my curriculum (Wikipedia1 says they are more common
| in non-metric regions). Or it may be just me. In any case, I
| find this notation ambiguous, so I would not expect a
| compiler to resolve it correctly.
|
| Edit: also, I would rather write (x + y)/2 if I wanted half
| the sum, that seems much more logical to me than moving non-
| integer factors around.
|
| 1 https://en.wikipedia.org/wiki/Fraction#Mixed_numbers
| fweimer wrote:
| > Edit: also, I would rather write (x + y)/2 if I wanted
| half the sum, that seems much more logical to me than
| moving non-integer factors around.
|
| Based on what I recall, there's a bit of an aversion
| towards writing / or / for division (or explicitly written
| multiplication). And $\frac{1}{2}(x+y)$ is more readable in
| inline text than $\frac{x+y}{2}$.
| MayeulC wrote:
| I agree, though I wish you had specified in what context
| that aversion was.
|
| To give a specific example, I can cite units in the
| metric system, often written as kg.s-2.J-1 instead of the
| more ambiguous kg/s2/J; which could technically be read
| as kg/(s2/J), giving kg.J.s-1.
| davorak wrote:
| The newest pull request is:
|
| https://github.com/typst/typst/pull/7137
|
| from what I can tell. The commits look two days old so work
| looks on going.
|
| I do not understand the current set of preferences laid out in:
|
| https://github.com/typst/typst/pull/7072#issuecomment-338580...
|
| I do not understand 8, 9 'my preference' column and why they
| would make the similar syntax render differently.
| laurmaedje wrote:
| (Author of the post and issue comment here.)
|
| The preferences there were honestly rather ad-hoc w.r.t to
| the pull request and the approach the pull request took. And
| (as the author laid out), the PR was a rather ad-hoc solution
| for a problem we discovered literally one night before Typst
| 0.14 was supposed to be released.
|
| The design thoughts there were a bit half-baked, which is why
| we've closed the PR and reverted the original change, to get
| more time to properly reconsider things.
|
| The math syntax has seen little change since Typst's initial
| release (except for the infamous precedence change in 0.3
| that triggered all this) and just has some quirks that
| haven't been properly ironed out yet. However, it will remain
| a focus now and we want to give it a proper cleanup.
| andrepd wrote:
| I really don't see the problem with the current notation. I find
| that is very simple and intuitive: function calls bind tightly,
| use a space to change that.
|
| f_i(x) vs f_i (x)
|
| 1/x(a+b) vs 1/x (a+b)
|
| ab vs a b
|
| So simple. Being too "smart" invariably leads to more headaches
| and confusion than just having a simple, consistent rule.
| zygentoma wrote:
| Exactly this!
|
| It is just plain simpler than the original TeX/LaTeX notation.
| fwlr wrote:
| From quickly messing around in the playground, it seems (in
| math mode) Typst treats multiple spaces identical to single
| spaces. A simple, consistent, flexible, and probably-not-
| majorly-breaking-old-documents rule would be "anything with no
| spaces has higher precedence / tighter binding than anything
| with one space, anything with one space has higher precedence /
| tighter binding than anything with two spaces", etc, and then -
| only within each spaces category - you apply one of the
| precedence rulesets described in the article. Any confusion or
| surprise can be solved intuitively and without thought by
| mashing spacebar.
| tonyarkles wrote:
| I agree with you conceptually, and am also laughing a bit
| thinking about how many people get angry about significant
| whitespace in Python and how much deeper down that rabbit
| hole "operator precedence changes based on whitespace" this
| proposal is :D
| IshKebab wrote:
| They missed another option: require brackets where it would
| otherwise be ambiguous.
| runarberg wrote:
| In mathup[1] I handle this by allowing authors to strategically
| place space around groups they want to operate on:
| e^ x-1 <- "e with x minus one as superscript" e^x - 1
| <- "e with x as superscript minus one. Same as e^x-1" f_
| i(x) <- "f with i of x as subscript" f_i (x) <- "f with
| i as subscript of x. Same as f_i(x)"
|
| I also implemented invisible operators (plus, times, function
| application, and separator) with special operators (`.+`, `.*`,
| `.$`, and `.,` respectively) so authors can be explicit about
| their intentions (and output more accessible expressions)
| f_i .$ (x) a / b.*(1 - x) sum_ X_ i.,j
|
| 1: https://mathup.xyz/
| vitriol83 wrote:
| are there any tools to convert large latex documents to typst ?
| it looks a huge improvement, but the migration path is the only
| thing that's stopping me.
| laurmaedje wrote:
| Pandoc [1] can convert LaTeX to Typst.
|
| [1]: https://pandoc.org/
| sureglymop wrote:
| I like typst but in all honesty I was a bit disappointed when I
| saw that they didn't have a backwards compatible math mode.
| Looking at all the shortcomings of latex, I wouldn't say the math
| notation is part of it.
|
| And since probably many people are very familiar with it, I would
| have liked for them to just keep that part.
| ajkjk wrote:
| It feels absurd to have this occur in the parser, as if you can
| somehow account for all the cases via guessing what people I
| mean. You absolutely _must_ have a grouping operation like {} at
| least available as a fallback.
|
| I feel like this is a lesson people keep learning over and over
| across programming languages: don't let your syntax try to infer
| the intended meaning of what was typed, just do something simple
| and predictable.
|
| So (b) seems like the only sane choice, but having the grouping
| operation being e^(abs(x)) is also crazy. You need something like
| TeX's e^{abs(x)}.
|
| Personally I think the "best" workaround for this is to decouple
| the text representation and the representation the editing
| happens in. Allow people to type e^abs(x) and then the _editor_
| translates that into e^{abs(x)} while letting you edit it as an
| exponential, but if you 're working on the underlying text file
| then you have to write e^{abs(x)}. For that matters, you can just
| have the editor represent it as a literal superscript.
|
| (My hunch is that this is generally much-needed across languages:
| let the editor do some of the parsing work. I think there's much
| to be gained by separating the two, because you can keep the
| parser of the actual language simple while still getting all your
| editing-efficiency improvements out of the editor).
| trueismywork wrote:
| I complained about this before and people dismissed me as an
| old timer. I did doubt myself as well to be honest. Its
| bittersweet to be correct.
| lou1306 wrote:
| I hate recurse to authority, but after a markup slash
| programming language has been written by Don Knuth and a
| macro system for it has been developed by Leslie Lamport,
| maybe one should take some notes so as to why things were
| done in a certain way?
| cruegge wrote:
| They're not infailable, though. For example, TeX's
| primitive for fractions is actually {a \over b}, LaTeX's
| \frac is a macro on top of that. The consequence is that
| while typesetting a formula, the engine does not know the
| current text size, since an \over further down the line may
| put the entire thing into a numerator. Dealing with this
| can be quite a pain when writing math macros.
| TimorousBestie wrote:
| I actually think Typst should ignore the design of TeX and
| LaTeX more--and especially the well-meaning advice of LaTeX
| veterans who have only ever known one way of typesetting.
|
| The situation reminds me of how Julia's evolution was
| guided in some aspects by some opinionated and vocal
| {Python, R, MATLAB} developers who never had any intention
| of transitioning to Julia, whether or not their advice was
| implemented.
| runarberg wrote:
| I am the author of a (somewhat) competing parser called
| mathup[1] which has a similar syntax. I based mine heavily off
| of AsciiMath which has {: group :} as a fallback grouping
| operator. I kept it, but if I would have done it over I would
| have replaced it with { group } and used {: group :} for curly
| brackets.
|
| I had a similar dilemma before I released 1.0.0 last spring,
| and decided against special cases like these. In Mathup binary
| operators (^, _, and /) always operate on exactly one group
| after the operator, regardless of (what I believe is) the
| author's intention. So 1/2(x, y) is the same as 1/x(i, j) is
| the same as 1/f(x, y). I only have a couple of exceptions
| regarding spacing on trig functions, and (what I believe is)
| the differential operator. But if you want an implicit group to
| e.g. under a fraction, in a superscript, you must either denote
| that with spaces e^ x-1, or with parens e(x-1) [I courteously
| drop the parens from the output in these troubled expressions].
|
| 1: https://mathup.xyz
| jraph wrote:
| > Personally I think the "best" workaround for this is to
| decouple the text representation and the representation the
| editing happens in. Allow people to type e^abs(x) and then the
| editor translates that into e^{abs(x)} while letting you edit
| it as an exponential, but if you're working on the underlying
| text file then you have to write e^{abs(x)}. For that matters,
| you can just have the editor represent it as a literal
| superscript.
|
| I'm pretty sure that's how LyX does it, possibly others as
| well.
| abdullahkhalids wrote:
| Typst has made some basic choices, which as someone who typsets
| a lot of math, makes it a no go.
|
| - The use of space character to also act as the escape
| character (latex use backslash) [1]. Not only does it cause
| confusion, I have to now escape everything $F=ma$ become $ F =
| m a $ in typst. Complex math equations will be complex no
| matter what - why make simple equations harder to type to make
| it slightly easier to type complex ones.
|
| - The lack of these grouping brackets (latex uses curly
| parenthesis).
|
| What I want from my typesetting language is "typsetting
| completeness". While there might be sane defaults, I want to be
| able to control every decision made by the typesetter by
| escaping and grouping things as needed. If the language doesn't
| have these features, by definition, it is not complete.
|
| [1] Latex also has to use space to act as ending delimiters.
| $\alpha x$ is correct and $\alpha\beta$ is correct, but
| $\alphax$ is not. But the solution to this is to allow $ax$
| which some flavors of tex do.
| runarberg wrote:
| As an author of a different math typesetting tool (mathup) I
| explicitly made the choice of making simple expressions
| simple to type at the expense of making complex equations
| less intuitive. But I still have the same problem as OP,
| where simple expressions break because the intuitive behavior
| is the opposite of what my parser does.
|
| AsciiMath (what my tool was inspired by) tries to be smart
| about this by parsing a/f(x) differently from a/x(f) and it
| looks like typst is making the same choose. I on the other
| hand opted to rather stay consistent. My reasoning is that
| the tool is fast enough, and I rarely (actually never) type
| my math expressions outside of an interactive experience
| where I can't view the rendered result as I type, so I can
| spot my mistakes immediately (usually fixed by adding a
| space, or surrounding something with parens).
| TimorousBestie wrote:
| > What I want from my typesetting language is "typsetting
| completeness". While there might be sane defaults, I want to
| be able to control every decision made by the typesetter by
| escaping and grouping things as needed. If the language
| doesn't have these features, by definition, it is not
| complete.
|
| Then LaTeX is not complete. Macros don't have to respect the
| grouping provided by curly braces in math mode, therefore you
| only have the illusion of control. Nobody in practice
| actually inspects the full package dependency chain needed to
| typeset a nontrivial document.
|
| Here's a proof of concept:
| https://tex.stackexchange.com/questions/748416/how-can-i-
| aut...
| abdullahkhalids wrote:
| Yes it is not. I think a replacement for latex is needed,
| but it needs to make better design choices than Typst.
|
| That said, Typst has many good things, like easy to write
| methods, which this new language should adopt.
| vitorsr wrote:
| > Typst has made some basic choices, which as someone who
| typsets a lot of math, makes it a no go.
|
| For me, breaking from not just a 40-year-old history of
| mathematical typesetting but also from the _American
| Mathematical Society_ recommendations is the dagger. Plus
| doubling work if you want to reuse what you wrote to render
| MathJax or KaTeX.
|
| > $\alpha x$ is correct and $\alpha\beta$ is correct, but
| $\alphax$ is not.
|
| Like you said, braces can be used so all of the following are
| valid: ${\alpha}x$, $\alpha{x}$ or the odd $\alpha{}x$.
| Voklen wrote:
| I love well-reasoned, thorough articles like this with all the
| tradeoffs considered. It makes me confident in Typst's future.
| eviks wrote:
| >pi(1 + 2) is a function call or just pi multiplied by three.
|
| another case for using proper notation p with some
| autosubstitution rules so that you can resolve the ambiguity
| immediately while typing (if pi is converted into p you backspace
| and let it stay pi as a function)
|
| But #functions also seems like a good option for readability
| runarberg wrote:
| MathML recommends using the invisible operators for invisible
| times or function application (&InvisibleIimes; [U+2062] and
| ⁡ [U+2061] respectively) to differentiate the two.
| eviks wrote:
| Unfortunately, they're... invisible. Though they can still be
| highlighted in an editor, so also helpful
| runarberg wrote:
| You notate the operation with * and $ (in mathup I use .*
| and .$ to make the operator invisible). Literal p is used
| both as a constant and as a function identifier depending
| on context so p(1 + n) can either be e.g. the (n+1)th prime
| or pi times one plus n. It is usually clear from context
| which one the author meant but if it is a problem explicit
| notation could help for sure.
|
| I have also heard that the invisible operators help with
| accessibility. I haven't tested this on my screen reader,
| but I suppose <mi>p</mi><mo>⁡</mo><!-->...<--> would
| read something like _"Pi of ..."_ whereas
| <mi>p</mi><mo>⁢</mo><!-->...<--> would read
| something like _"Pi times ..."_ all the while
| <mi>p</mi><mrow><mo>(</mo> would just read _"Pi [open
| parenthesis] ..."_.
| eviks wrote:
| Good point about primes, not enough symbols for
| uniqueness, so just p isn't enough! Though using two
| symbols ( .* ) in place of nothing is too dirty, better
| use an invisible and color highlight the spacing between
| p and ( to indicate to the plain text reader the
| difference.
|
| Win screenreaders understands 2. _3 (pronounced two
| three) vs 23 (twenty three), though it doesn 't pronounce
| the operator, neither in a._2 vs a2 (though pronounced
| differently). But this could be fixable, so also good
| point about accessibility
| Ericson2314 wrote:
| IMO a math mode that was less syntactic but more semantic would
| solve all these issues exp(e, abs(x))
|
| Boom; fixed. Can't say I really mind the verbosity either.
| __mharrison__ wrote:
| I'm not a big math mode user (but I use typst a lot).
|
| Latex equation compatibility seems like a blocker for many. Maybe
| they should have a library that allows one to drop in latex
| formulas?
| jeremyscanvic wrote:
| Seems to be what those guys are up to:
| https://typst.app/universe/package/mitex/
| sconeman wrote:
| For those not familiar with the Typst library, it feels important
| to mention there is an `attach` function which gives much more
| explicit control of sub/superscript type-stetting. I'm surprised
| the blog didn't mention this at all as an option.
|
| Docs: https://typst.app/docs/reference/math/attach/
___________________________________________________________________
(page generated 2025-10-30 23:01 UTC)