December 2025
In any language design, the total time spent discussing a feature in this list is proportional to two raised to the power of its position.
- Semantics
- Syntax
- Lexical syntax
- Lexical syntax of comments
In any language design, the total time spent discussing a feature in this list is proportional to two raised to the power of its position.
- Semantics
- Syntax
- Lexical syntax
- Lexical syntax of comments
Also called: concrete syntax, surface syntax
Semantics: Greek
\frac{\delta, \delta'; \pi_{m + 2}(\Theta); \sigma \vdash {e}_i \Downarrow \theta_i \qquad \bar{{e}} = {e}_1, \ldots, {e}_n}{\delta, \delta '; \Theta; \sigma \vdash {e}(\bar{{e}}) \text{ FAIL}}
Syntax: Latin
Hope this helps!
Consider a simple program:
\boxed{\texttt{let $x$ = 2 + 2 in $N$}}
Substitution: replace occurrences of x with 2 + 2, or 4?
\texttt{let $x$ = $M$ in $N$} \;\longmapsto\; \underbrace{N[x := M]}_\text{substitution}
Environment: partial function \sigma maps name x to 2 + 2, or 4?
\langle \sigma, \, \texttt{let $x$ = $M$ in $N$} \rangle \;\longmapsto\; \langle \underbrace{\sigma[x := M]}_\text{extend env}, \, N \rangle
See also The Next 700 Programming Languages (Landin 1966)
const, let, var,
myx = v, x := v, x ← v{…}BEGIN…ENDand more…
In any language design, the total time spent discussing a feature in this list is proportional to two raised to the power of its position.
- Semantics
- Syntax
- Lexical syntax
- Lexical syntax of comments
Implication: priority is backwards
i.e. concrete syntax exponentially less important
Too often, concrete syntax decisionmaking is:
And that is a shame!
Concrete syntax is the foremost user interface for most programming languages.
also software libraries, mathematical theories (notation), etc.
[m]illions for compilers, but hardly a penny for understanding human programming language use. Now, programming languages are obviously symmetrical, the computer on one side, the human on the other. In an appropriate science of computer languages, one would expect that half the effort would be on the computer side, understanding how to translate the languages into executable form, and half on the human side, understanding how to design languages that are easy or productive to use.
John Pane (1985), via Newell and Card, via Felleisen, emphasis mine
Both important, but metatextual!
By relieving the brain of all unnecessary work, a good notation sets it free to concentrate on more advanced problems, and in effect increases the mental power of the race.
A. N. Whitehead, emphasis mine
If we have function keys to generate syntactic constructions, for example, which is the ‘notation’—the keys we press, or the words we see? Various factors will determine the user’s view, such as prior experience; the units operated upon by the editor […] and whether a simple mapping can be perceived between […] a function key […] generating a simple indivisible unit of a few words.
T.R.G. Green (1989), emphasis mine
\boxed{\vdash \varphi}
“can be proved”
\boxed{\models \varphi}
“is modeled by”
The following definition is purely syntactic:
\begin{aligned} \varphi &:= \ldots \\ &\mid \varphi_1 \land \varphi_2 \\ &\mid \varphi_1 \to \varphi_2 \\ &\mid \ldots \end{aligned}
“Just symbols,” but if I went onto define implication using \land, you would probably hate me
Functional programmers: monadic bind
C-style programmers: bitwise right shift assignment
\llbracket \texttt{x >>= 1} \rrbracket \approx \llbracket \texttt{x = x >> 1} \rrbracket
JavaScript programmers: maybe no idea?
Despite best intentions, we are pareidolic creatures
If symbol perception is all relative, why design concrete syntax?
It has become fashionable to regard notation as a secondary issue depending purely on personal taste. This could partly be true; yet the choice of notation should not be considered arbitrary. It has consequences and reveals the language’s character.
Niklaus Wirth (2006), emphasis mine
let-binding) built on top of a smaller core
language (e.g. applicative expressions)definelambdasbecomes
becomes
becomes
Pre-2015: prototypal inheritance
Post-2015: class-based inheritance
class syntaxclass—you’re
often better off without!Both obscure the core language (syntactic abstraction).
Worth considering when defining your own
Subtyping: types form a lattice over <: relation
\boxed{ \bot \;<:\; \texttt{"hello"} \;<:\; \textsf{string} \;<:\; \top }
Gradual typing: typed-untyped codebase interaction
\boxed{ \bot \;<:>\; \textsf{Dyn} \;<:>\; \top }
How to express any possible type?
\textrm{isString} : \mathrm{???} \to \textsf{boolean}
How to express any possible type?
\textrm{isString} : \red{\mathbf{\top}} \to \textsf{boolean}
How to express any possible type?
How to express any possible type?
Problem: any is \mathsf{Dyn}, not \top!
\boxed{ \bot \;<:>\; \textsf{Dyn} \;<:>\; \top }
\mathsf{Dyn} is unsound: breaks typing guarantees, causes major incidents
any (adj.)
- one or some indiscriminately of whatever kind […]
- unmeasured or unlimited in amount, number, or extent
source: Merriam-Webster
| Dynamic | Top | |
|---|---|---|
| TypeScript (JS), Luau (Lua) | any |
unknown |
| Flow (JS) | any |
mixed |
| mypy, Pyre (Python) | Any |
object |
| Sorbet (Ruby) | untyped |
anything1 |
| Hack (PHP) | dynamic |
mixed |
| Elixir (Erlang) | dynamic |
any2 |
| Typed Racket (Racket) | -3 | Any |
| Scala, Kotlin | - | any |
| Swift | - | Any4 |
any for \mathsf{Dyn}, and the other
half for \top
any all have different
names for \top
unknown, mixed, object,
anythingterm for \top, but
the documentation uses any
Of note: Stefik & Siebert (2013), An Empirical Investigation into Programming Language Syntax
Or, how I became an \eta-expansion scrooge
Promise chainingasync/await (today’s
world)Promise chainingasync/awaitasync/awaitPromise chainingPromise chainingPromise chainingPromise chainingPromise chainingDPromise chainingrunA()
.then(a => Promise.all([a, runB()]))
.then(([a, b]) => Promise.all(
[runC(a, b), runD()]
))
.then(([c, _] => …)(This is my \eta villain origin story btw)
Promise-chainingThis is all completely incidental, yet resulted in a loss of expressive fluency in async-handling constructs!
Languages can go through tremendous semantic changes based on completely incidental syntax
Too often, concrete syntax decisionmaking is:
And that is a shame!
If we take seriously the idea of programming languages as user interfaces, then concrete syntax matters just as much as semantics.
Concrete syntax shapes the way people understand semantics, and in turn shapes the semantics themselves.