Designing a programming language

I've been thinking about making an experimental language that improves upon Rust (a 'modern' systems programming language). Here are some thoughts regarding Rust, and ideas for what the aforementioned experimental language might look like.

I used to have a few projects written in Rust, a language with an affine type system that helps enforce memory safety invariants. The way that Rust handles memory is conceptually quite fun, as it involves an idea of "movement" and "borrowing" which isn't very common in other well-known programming languages. Despite this, I actually dislike Rust due to the inflexibility of its 'borrow checker', as well as its cumbersome syntax.

Other programmers have said plenty about Rust's benefits, and Rust's detractors have written enough about its issues, so I'll only provide a brief overview of what I appreciate and dislike about the language.

In Rust, you don't explicity free dynamically allocated chunks of memory, because the compiler infers where and when memory can be freed. This is a very nice feature because it prevents common manual memory management bugs (e.g. 'use after free'), and it doesn't rely on a garbage collector to manage memory; in other words, Rust is able to have safety without sacrificing speed.

However, the 'borrow checker' is (necessarily) very strict, which makes it very difficult to write certain abstractions such as doubly-linked lists. There are several solutions to this issue (notably, the 'GhostCell' abstraction) but such work-arounds are typically complex, make various compromises (e.g. with thread safety), and abuse Rust's more esoteric features. It is also worth noting that Rust's syntax makes it very difficult to write complex enough abstractions, because the syntax carries around lots of information but doesn't 'scale' too well.

If I were to make a language that improves upon Rust, I'd want it to have the following traits (no pun intended):

  1. concise, good-looking syntax that 'scales' well
  2. varying granularity (different bits of type/lifetime information can be omitted for brevity, or included for clarity)
  3. memory system that allows for a 'sliding scale' of safety
  4. ideas like copying and pointer arithmetic should be put into typeclasses, so a function's type can specify what it can and cannot do with a reference
  5. all data should have move-on-assign semantics by default, rather than copy-on-assign semantics, for consistency
  6. copying can still be used 'under the hood' for efficiency
  7. <- should be used for assignment rather than =, because it expresses 'movement' better
  8. syntax should consist of simple modular expressions, which should allow for variation but also repetition

The last point may sound redundant, because most programming languages already have syntax specified by some sort of grammar that consists of a series of modular rules. However, the last point is more about the idea of 'variations on a theme' that occurs in disciplines like art, architecture, and music. While similar to the idea of a formal grammar (and this hypothetical language would indeed have a formal grammar), the idea of 'variations on a theme' is founded upon aesthetic principles beyond what can be formally specified. networking infrastructure amidst flowering cherry blossom trees
In the above picture, there are several different modular patterns at work, both natural as well as man-made. While it would be possible to approximate all these patterns using some sort of grammar or something like a Lindenmayer system, the patterns are ultimately too subtle to perfectly reproduce. Instead, a human eye is required, and an artist would indeed have more success in reproducing the 'look' of those patterns than a computer would.
a porcelain plate with a flowering branch drawn on it

In summary, beauty requires aesthetic intuition, and it is therefore impossible to make a truly great programming language using mathematical intuition alone. If I continue with the experimental language, I expect that the aesthetic goals will be harder to achieve than it will be to write any sort of type-checker or compiler, and even if I implement the language in its entirety, I may end up failing to make it as beautiful as a programming language ought to be.