Philosophical question: Why was `=` chosen over `#` for headlines in the Typst syntax?

Does someone have more insights what advantages the # had/has for functions? Since large parts of the syntax would have been Markdown-compatible out of the box, most continuous text (books, scripts, screenplays,…) could have been rendered in any of the many popular Markdown editors.

What made = so much better for headlines that it outweighed these big potential benefits? Or what does # offer that §$%\ for functions wouldn’t have offered?

2 Likes

There was recently a discussion, you can read a bit more about it here: Suggestion: Introduce Markdown-Compatible Headline Syntax in Typst (`# Headline` vs. `#function`) · Issue #5386 · typst/typst · GitHub

1 Like

At some level, the decision to use = for headings and # for code prefixing is really just preference and vibes. But this works well for Typst! It becomes more accessible and parseable for humans with this choice, and I wouldn’t choose differently if I were restarting.

First off, #func() just looks right ¯\_(ツ)_/¯.
The hash takes up a good amount of space horizontally and vertically, and as a bonus it’s familiar to non-programmers as a word prefix with context sensitive meaning.

The only major conflicts are the use of # as a shorthand for “number” (but this is becoming old-fashioned) and it’s use in markdown headings. But there’s already precedent in other markup languages for using = to denote headings — e.g. djot, AsciiDoc — so it’s a defensible choice.

Code editors can also recognize = at the start of lines as a heuristic to infer the language of a random text file. If you open a new tab in VSCode and just start typing, it may start to do syntax highlighting all on its own. How does it know which language to use for highlighting? Heuristics. Using = for headings makes for a pretty good one to differentiate from markdown in this case. Which especially enables proper highlighting of code blocks in Typst.


But just for fun, let’s go down the list of other possibilities for Typst’s code prefix.
(This is very opinionated and only half serious; have your salt grains ready)

  • = — we could just swap the two symbols. (any spreadsheet fans here?) But = is used enough in regular prose and discussion that it’s likely to be annoying. This is especially bad for math mode syntax, so that’s not gonna work. Also it doesn’t have enough height, it doesn’t stand out enough against other characters.

  • @ — the at-sign could work, but now our symbol stands out too much. @ is better for separating email domains than introducing code. It’s also semantically nice to use for references, we’ll keep it there.

  • \ — backslash is maybe fine, but then we have to use some other character to escape our special symbols like \*, \$, \u{abcd}. And programmers are already familiar with \ for used for character escapes, so it becomes an anti-feature. Also it’s too tall: backslash breaks up the readability of prose when inserted too much. Finally, Typst wants to shed LaTeX’s baggage. This syntax is actively unhelpful and makes the language less intuitive to many.

  • % — another reasonable contender, but percent would remove the ability to have percent-literals, box(width: 100%), which is just really nice and obvious semantically. Also another too large boi.

  • $ — too tall again, but also already heavily associated with math input. I know I’m contradicting myself on the “LaTeX baggage” front, but using $ as a delimiter was one of Knuth’s better syntaxes. There is precedent for dollar-sign as a prefix in shell scripts, but that’s not that common outside the command line.
    Also: $ isn’t common across keyboards. The US dollar is pretty dang stable (for now), but it’s not omnipresent. Typst’s code prefix should be more universal than its math delimiter: code will be used far more often than math, and math will mainly be used by those with more technical knowledge.

  • & — imo, ampersand is a bit of a dark horse as a prefix. But too tall, and used enough in English prose that it’s a tad awkward. I also dont want C coders thinking we have raw pointers here.

  • — the “lozenge” character has precedent in the Pollen language. But nobody has this on their keyboard.

  • ~ — tilde could be nice, but it’s less common on keyboards, and now we have a problem that the character is too short. We use tilde as a shorthand for non-breaking spaces because it doesn’t call attention to itself. Not fit for a common prefix.

  • § — cute. Too tall. Can’t type it. Not a lawyer. Pass.

  • ` ` — nothing. That’s right, “nothing” is also an option for a code prefix, but a horrible one! Imagine defining a variable named space and then having your astronomy papers turn into syntax errors. Horrid. The character prefix makes parsing context-free. Without it, code and prose are harder to separate not just for computers, but also humans.


In the end # wins because it’s the only common character that stands at letter height and exists on everyone’s keyboards. And since there’s a precedented replacement for heading syntax, it’s worth the change.

3 Likes

Hehe, thank you for the thought experiment. Interesting answer!

I guess something like {% h(30%) %} and nothing inside established code blocks were the function doesn’t need further indication (like it is) would also have been possible, but of course #h(30%) saves 3 characters and 2 spaces on top there. And I was more interested in the single character alternatives, as this is unquestionably more elegant than anything like {{ etc.

Certainly, # is a very solid choice in terms of readability and low alternative usage. Still, I’m very curious how many people will stumble over the fact that for common prose, Markdown syntax would have been within reach with the exceptions of headlines and strong. I hope Typst becomes so successful that we are about to find out :smiling_face::tada:

Oh, I think this would have been a good one, until I realized that it is not easy to type on English keyboards. (On standard German ones, this is simply Shift+3.)

1 Like