My dream programming language would be able to express the syntax and semantics of every other programming language idiomatically. In this framing a good programming language would have few builtins1 but would still be able to manifest many more specific features as library definitions.

I take a very general view of features. Optimizations are included in this list because in order practically exploit the fact that one programming can express the semantics of another, it must be able to match its performance2. Thus optimizations are more or less “features” for a programming language; they help determine what the programming language can practically be used for.

Maximizing which features are expressible as part of the standard library, maximizes what users are able to rewrite. If users don’t like the features the language provides in its standard library they can write their own. Such a language is maximally flexible for users.

Of course, actually using custom built features comes at the expense of interoperability with the broader ecosystem. But I think it is better to give users the choice of what they need to interoperate with, rather than artificially restricting it to guarantee good interoperability3.

With a sufficient floor of metaprogramming capabilities, any feature could be implemented as a builtin or as part of the standard library. I collect this list so that I can sort/consider which features are more primitive and which are the most useful to be able to reprogram. Each programming language features thus becomes both a test and an axiom for programming language expressivity.

Meta note: I went through and made a bunch of these notes public. There’s still a lot of links that aren’t public. A lot of the pages themselves are stubs and have highly varying levels of research/detail/revision put into them.

meta programming

Features enabling and enabled by metaprogramming. In some sense these are the most important because they’re what enables implementing features in terms of each other. I’m also interested in evaluating which of these features are the most irreducible.

Features providing metaprogramming ability:

Features implementable by metaprogramming:

  • embedded query languages, e.g. LINQ
  • EDSLs in general get better as metaprogramming is better supported by a programming language

Features kind of like metaprogramming in terms of the expressiveness they provide:

working with (generally monadic) effects

This category encapsulates language features that make working with effects easier:

working with coeffects

concurrency / distributed programming

Working with data

pattern matching:

Accessors / key paths / lenses:

  • generic/uniform syntax for arbitrary n-functors/lenses

optimizations

evaluation order

types

Primitive types:

Broader concepts:

Weird/highly non-standard stuff:

typeclasses / traits

Typeclass features:

standard library

The main purpose of a standard library is to define the shared vocabulary that all programs can coordinate around. Because more primitive features are implemented as part of the “standard library”, it places an even larger burden on the design of its standard library.

Properties the standard library should have:

  • layers of primitiveness: that allow giving up progressive amounts of interoperability for the ability to redefine larger parts of the language
  • facilitate migrations between standard library types to make the decision to include/not-include various things as unimpactful as possible

Must haves:

Things to consider adding to a type class hierarchy beyond what Haskell has:

modules / scoping

lifetimes / scoping

control flow

Dis-preferred:

code location / relocating code

testing

See also

  • programming language benchmarks for ways of testing what features are useful for programming tasks
  • my programming language for features that are core enough to warrant consideration as primitives for my programming language design project
  1. Features implemented with special support in the compiler. Also sometimes called intrinsics (e.g. by the rust compiler) 

  2. Even though the lambda calculus is Turing complete and can technically implement arbitrary floating point arithmetic, no one is seriously trying to train neural networks using it. 

  3. This is my largest problem with the philosophy behind the design of go-lang. While true that a simpler language leads to more uniform programming styles, it also makes it harder to build shared abstractions.