My Thoughts on Programming Languages

Posted on Jul 3, 2021

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.

Language Programming Hours
C > 100
C++ < 100
Python > 1000
Scala > 200
Nim > 100
Java > 50
Rust 2 weeks
V-lang .25

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

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 Y, you can’t easily grab packages X, Y, and 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 with pip - just seems to be an odd design choice. It’s possible to build scala programs exclusively using scalac, java programs with simply javac, 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.

Portability

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
C No No No No No N/A No No OK Yes
C++ No Yes Yes No No N/A No No OK Yes
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
V-lang No Yes No Yes Yes Yes Yes Very Fast ? Yes

Favorite Language

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.