I’ve written code in well over a dozen programming languages. I’m always ready to learn another, and there’s always someone eager to sell me on their favorite.
However, if I’m going to learn a new language at this point, it has to be a better fit for me than the ones I’m already using and the ones I’ve already tried and abandoned. No language is perfect, and I could criticize even my favorites, but some are a better match to my needs and desires than others.
So to save time, here’s what I’m looking for in any new programming language, with examples to try to clarify what I mean.
Platform support
Unix family, specifically including macOS and Linux.
AMD64, ARM and RISC-V.
I don’t care about Windows.
Licensing
Open source with a free software license, so it can’t suddenly be destroyed by a malicious corporation.
Syntax
I have a hard time remembering syntax, so I want something that’s simple. Ideally it should also be clean and easy to read, with a minimum of sigils and operators.
Good: Scheme, Go, Ruby
Adequate: Java, Swift
Horrible: C++, Perl, Rust
Library
I want the standard library to have good coverage of POSIX APIs. Again, I don’t care about Windows. The standard library should have support for TCP/IP connections, UDP, Unix domain sockets, Unix permissions, standard cryptographic algorithms, JSON and XML and base64, Unicode, and so on, or else it’s just a toy language.
I also want a standard package manager. Just one, maybe two tops.
Good: Ruby, Go
Adequate: Java
Horrible: Scheme, JavaScript
Interoperability
Since I’m not going to be able to find everything for this new language, I need to have the option of occasionally using code written in something else. That means I want some reasonable FFI option.
Good: C, Zig, Kotlin.
Adequate: Go.
Horrible: Java.
Language features
These are in approximate descending importance:
Basic types: unsigned bytes, 32 and 64 bit unsigned integers, signed integers, strings, variable-length arrays, hashes/maps.
Decimal floating point numbers (decimal64 and decimal128).
UTF-8 support throughout the entire language.
Static typing with compile-time type checking.
Lexical scoping.
Object-orientation through composition.
Automatic memory management, either through a fast garbage collector or through some sort of unintrusive and robust reference-counting system. (Examples: Go, Rust.)
First-class functions.
Functions that can return tuples. (Examples: Ruby, JavaScript, Go.)
Fast compile times. (Example: Go. Horrible: C++.)
Trivially easy cross-compilation. And by trivially easy, I mean “set one option on the compile command and you’re done” easy. (Example: Go.)
More advanced types: arbitrary precision integers, arbitrary precision decimal floating point numbers, rationals.
Immutability by default. (Examples: Scala, Haskell.)
Tail-call elimination.
Function overloading.
Parametric polymorphism.
Facilities to make safe concurrency easier, such as CSP structures. (Examples: Go, Kotlin.)
Small binaries and a lightweight runtime. (Examples: Zig, C.)
A good native GUI option for macOS and Linux.
One defined standard set of formatting conventions, and a formatter to implement them. (Example: Go.)
Unimportant
Things I don’t particularly want or care about but I’m OK with them:
OO class inheritance.
Ubiquitous type inference. (I prefer to state my types, thanks.)
Multiple implementations.
Option types.
Binary floating point numbers.
Undesirable
Things I don’t want, but I’m willing to put up with them:
Pointers.
Null (used to represent an absent value, like in SQL).
Nil (a zero value, like in Go).
Deal killers
There are some things I’m just not willing to put up with:
Semantic whitespace. (Examples: Python, YAML.)
A de facto requirement for containers or virtual environments. (Examples: Python, JavaScript.)
A required special IDE. (Examples: Smalltalk.)