Roel
March 30, 2026, 10:50pm
1
Just out of curiosity, I tried to automate the generation of this not-so-pretty equation:
$ sum_(i=1)^3 i =& 1 + \
& 2 + \
& 3 \
=& 6 $
I’ve tries this is a few ways:
$ sum_(i=1)^3 i =& #range(1, 4).map(it => [#it]).join([+ \ &]) \
=& #str(range(1, 4).sum()) $
$ sum_(i=1)^3 i =& #range(1, 4).map(it => str(it)).join([$+$ \ $&$ ]) \
=& #str(range(1, 4).sum()) $
$ sum_(i=1)^3 i =& #range(1, 4).map(it => str(it)).join("+ \n & ") \
=& #str(range(1, 4).sum()) $
I think there should be a better way to convert strings and numbers to math, but how?
Y.D.X
March 31, 2026, 2:15am
2
I think this is a perfect use case of Evaluate Function – Typst Documentation — you want to generate typst code and the possible expressions are limited.
#let expr(n) = {
"sum_(i=1)^{n} i =".replace("{n}", str(n))
for i in range(1, n) {
"& {i} + \ ".replace("{i}", str(i))
}
"=& {}.".replace("{}", str(n * (n - 1) / 2))
}
#eval(expr(6), mode: "math")
You may also generate it more programmatically as below, but I don’t think that would be more reliable than eval.
#{
let align-point = $&$.body
math.equation({
import sym: eq, plus
eq
align-point
"1"
plus
linebreak()
align-point
"2"
plus
})
}
See also Pack complex content with data loading functions in Tips on debugging Typst code, including the dark magic
#raw(
yaml.encode($= &1 + \ & 2 +$),
lang: "yaml",
)
func: equation
block: false
body:
func: sequence
children:
- func: symbol
text: =
- func: space
- func: align-point
- func: text
text: '1'
- func: space
- func: symbol
text: +
- func: space
- func: linebreak
- func: space
- func: align-point
- func: space
- func: text
text: '2'
- func: space
- func: symbol
text: +
3 Likes
Roel
March 31, 2026, 8:26am
3
Ah, thanks! I guess there is some limitation that I cannot just have a function (e.g. join) insert bits of code into an equation, as I’m familiar to do with LaTeX, so the processing of the code into contents has to be made explicit by eval? Probably this has to do with functions being pure?
Y.D.X
March 31, 2026, 8:45am
4
How about this? It’s a bit hacky, but physica – Typst Universe and many packages/documents use it.
$ S = #eval(expr(6), mode: "math") $
It can be done! Without string wrangling or eval or a third party package. The key is not to convert strings and numbers to math, but just use math to begin with.
#let N = 6
$
sum_(i=1)^#N i =
#range(1, N).map(num => $& num +$).join($ \ $) \
& #N \
=& #range(N + 1).sum()
$
5 Likes