My Thoughts on Programming Languages
In this post, I compare some languages I’ve worked with based on features that are important to me, then at the end, I decide my favorite language.
I don’t really keep a timer on how long I spend writing code, but I’d feel pretty comfortable claiming that I spent the following amount of time in the following various languages.
At the end, I rank languages with the features I care about.
I barely spent any time in V, but I feel comfortable making statements about it as it is a fairly basic language - more or less GO with some notable improvements.
It didn’t take me long to skim through the V documentation. There just isn’t much to V.
If you see a question mark in a field below, it probably means its been too long since I last used that language to remember if it has that certain feature.
Homoiconicity which in practice for me basically boils down to being able to rewrite the AST on the fly and is really important to me because its absolutely required to make a good DSL. For hardware design, languages such as Verilog or VHDL are quite simply in my opinion, the wrong tools and I think the ideal hardware design language could possibly be created as a DSL within an standard programming language.
First Class Package Manager
I also include first-class package manager as a feature to be considered
simply because I dislike writing makefiles. I don’t consider scala SBT
and or scala Mill as first class package managers because it’s more or
less impossible to do offline builds with the tools. That is, if you’re
trying to build
my_package which depends on
X which depends on
you can’t easily grab packages
my_package, store them
locally on your computer, disconnect from internet, and then build your
scala binary. Its possible in theory, but extremely difficult in practice.
This makes scala a really terribly choice for offline work. In principal, this isn’t an issue for me as a have a reliable internet connection, but having a language environment that depends on an internet connection seems flawed by design.
Also, scala, java, and Rust require the package manager to run packages with
dependencies. This would be like needing to run most of your python programs
pip - just seems to be an odd design choice. It’s possible to build
scala programs exclusively using
scalac, java programs with simply
and rust programs with just
rustc in theory, but this is really difficult
in practice. The scala compiler is incredibly slow, doesn’t support parallel builds, or
build file caching by default. SBT and Mill can help with caching, but the
caches they build seem to become currupted regularly.
Fast Compiler and Error Messages
Also, all these languages have really slow compilers except for Nim and V-lang.
Nim’s error messages aren’t very good. This hasn’t been an issue for me as I’ve been writing software for quite a while and can usually infer what made the compiler unhappy. But for a newcomer, this could easily be an issue.
As of this writing, I haven’t spent enough time in V-lang to make any claims about its error messages.
For me, portability means that said language can effortlessly be brought to a new architecture. C, C++, Python, Nim and V-lang all only require that the target architecture have support for Linux and the GNU C Compiler. This is important to me as I am a computer engineer by trade and strongly dislike the x-86 ISA. I like the ARM, RISC-V, OpenRISC, MIPS, and POWER ISAs and do my dev work nearly exclusively on POWER and ARM machines. It can be troublesome to get the other languages working seamlessly on architectures other than x-86 as they either require good JVM or LLVM for other architectures, which isn’t readily guaranteed.
Language Comparison by Features
|Language||Homoiconic||UFCS or Classes||Templates/Generics||Function Typing||First Class Package Manager||Package Manager Separate from Build Tooling||Scope Based Memory Management||Fast Compiler||Error Messages||Portable|
|Python||Not by design||Yes||Yes - Duck Typed||N/A||Yes||Yes||No||N/A||Very Good||Yes|
|Scala||Yes with Macros||Yes||Yes||Yes||No*||Not Practically||No?||Very Slow||Bad||No|
|Nim||Yes with Macros||Yes||Yes||Yes||Yes||Yes||Yes||Very Fast||Bad||Yes|
|Java||Not by design||No||Yes||Not Really?||No||Not Practically||No||?||?||No|
|Rust||Not by design||Yes||Yes||Yes||Yes||Not Practically||Yes||No||OK||No|
I think it comes down to Nim, V-lang or Rust. I really like the memory safety emphasis in Rust, but idiomatic Rust is so different from most other languages, that it still feels unnatural to me.
Nim is a nice all round language with really no major drawbacks.
V-lang is also very nice, I just wish it was homo-iconic. V-lang actually seems to be a perfect fit for bare metal work as does Rust.
Python is nice for quick and dirty prototyping, would never use Python in production, or for a computationally intense application(which accounts largely for most application I write - simulators, compilers, and such).
Languages I Reject
I completely reject C++ as it has too many features. C is alright, but with V-lang, I get C without makefiles.
Scala as a language is fine. It is pleasant to use and has nice syntactic sugar. My only issues are the jvm, which still takes too long to start up and is very large in size - between 200MB and 1GB depending on the JVM config. This makes for very poor container spin up time, which is a problem as I often use containers to do unit testing.
Scala SBT and Scala Mill are also very unpleasant tools to use. Mill is
worse than SBT. Simply running
mill --help will fire up an entire mill
compile server before it realizes it only needs to print the help screen.
Java is too verbose.