Tech News
← Back to articles

A Review of Nim 2: The Good and Bad with Example Code

read original related products more articles

I've been using Nim for about 1-2 years now, and I believe the language is undervalued. It's not perfect, of course, but it's pleasant to write and read. My personal website uses Nim.

After reading a recent article on Nim ("Why Nim") and the associated HN comments, it's clear that comments and some information about Nim are misleading and outdated. Since Nim 2, a tracing Garbage Collector is not the default nor the recommended memory management option. Instead, the default memory management model is ORC/ARC, which supports C++-esque RAII with destructors, moves, and copies. When you use ref types, your object instances are reference-counted, similar to a shared_ptr in C++, but it does not include atomic counters by default (use the switch --mm:atomicArc , which will likely be the default in Nim 3*).

In fact, you could use Nim as a production-ready alternative to the upcoming Carbon language. Nim has fantastic interoperability with C++, supporting templates, constructors, destructors, overloaded operators, etc. However, it does not compile to readable C or C++ code, which is unlike Carbon's goals.

In this article, I review the good and bad parts of Nim 2. I'll write a tiny key/value file format that can load a user-declared object to demonstrate how some of Nim's features compose in powerful ways. Hopefully, this code example will give a good feel for the language. If you prefer to start with code, feel free to jump to the example first.

I'm not going to discuss subjective dismissals of the language, such as whitespace or case insensitivity, which IMO are not reasons to dismiss a language.

* The Nim team is currently working on Nim 3 (called Nimony), a new iteration of the language. The largest design change is NIF, an intermediate human-readable format (similar to Lisp). NIF enables incremental compilation, a better macro system (simpler to implement), and better tooling. Here is a link to a document describing the design and associated blog post.

A common question I see online is: What sets Nim apart? In other words, why should you use Nim over any other language it competes with, such as C++, Go, Rust, JavaScript, or Python? In my opinion, there isn't just one unique "ground-breaking" feature or quality that sets Nim apart from the pack: it's the language as a whole. Overall, Nim is one of the most concise, flexible, and performant languages publicly available.

Nim is a systems programming language that feels much like a high-level scripting language like Python, as it generally requires less code to do actual work (minimal boilerplate; here's a chatroom in 70 LOC), i.e. it is concise. Nim is flexible as it has some of the best meta-programming capabilities and can be compiled to JavaScript (for a web frontend) or to a native executable (via C, C++, or Objective-C); it has arbitrary compile-time execution, that is: any code written in Nim can execute at compile-time. Nim can produce code that is similar in performance to other systems programming languages (C, C++, Rust, Odin, Zig). If you need to squeeze out extra performance, you can write lower-level style code, use SIMD intrinsics (e.g. using nimsimd) and/or generate code, e.g. here's how to generate CUDA code at compile-time with an emit pragma.

Here is an overview of some of Nim 2's features that make the language a joy to write in and hopefully will allow you to gain an idea of what Nim offers. This list is grouped by category from most to least commonly used:

Here's the code for the full example in the Nim Playground or as a gist.

... continue reading