One day I stumbled upon a language called Nim. At first glance, I thought this is some python clone. After seeing benchmarks though, my opinion changed drastically. The fact that you can be as productive as with python, and get the performance comparable to C++ seems very surreal to me. However, Nim isn’t just insanely fast for its simplicity. You may well say that TS is more complicated than Nim.
To go from imagination to reality, I will showcase how you can define object. Example shows whole spectrum of flexibility language can give you, all as simple as possible.
As documentation hints we are not finished yet, what might be unclean is concept of concept (yes). This little unusual, but very simple in its nature. If code, written in concept block, does not compile, you will get error stating that generic argument expects Component and not a string for example. This syntax also shows that you can test code conditionally. If c + c is still c, type is valid. Though why do we even check if c + c is still c, what kind of a nonsense would that be if we got something else? Well, when it comes to operators, everything is possible with Nim. Now sit tight.
Okay. So… If it wasn’t creasy before, now it definitely is. You can fall into two groups at this point. Either you are absolutely disgusted and horrified by ambiguity, or, totally amazed by the clarity. If you fell into the first group, you should probably safe your sanity for something more important and leave. On the other hand! For the group number two I kindly recommend to stay, as this is just a beginning. First we will explain the operator code.
When you enclose function name inside ``, it becomes an operator and can contain any sequence of character. In this case we used infix operator, which is operator always between two arguments. Even though this is operator, we can invoke it the ugly way as a function, `+`(a, b).
Next is a test code, the comment should explain well that code inside a when block will get compiled only when we want it to, with very little effort. Common testing process can be broken into 4 steps.
- write the function,
- write test right under it
- (optional) initialize some state beforehand in different block
- ‘nim r module.nim` and if test passes, you can move on.
Other nice surrealism Nim brings is a fact that first argument of any function can be used as its receiver. This allows you to unwrap nested prentices as:
c = this(that(andThat(a)))
# can be turned to
c = a.andThat().that().this()
# you can go even further and omit the prentices(spooks)
c = a.andThat.that.this
This is still just a basic staff though, we did not get to the real juice. (metaprograming)
We can actually define all 4 operators for our base type in 6 lines of code, without repeating any logic we already written.
Nicely done, isn’t it. Don’t forget that we have macros too, and they are nothing like macros in C or proc macros in Rust! Get that out of your head immediately!
Of course, to quickly go through a template, all it does is substituting code and code blocks (You can pass code blocks too!). Very good example of using a code block is benchmark template:
We can define what types template expects which makes using api more pleasant. Though as Nim manual states, if you can use template, don’t use macro, if you can use generics, don’t use template. Last thing we will do is to showcase a macro.
To conclude this matter, I learned about the Nim Programming Language just Yesterday (since I wrote this article), and got absolutely hooked up. I have to admit, language features are little overkilling some things, so I was concerned about compile time. There is no better comparison then Go compiler, as it is famous for its speed. I decided to stress test both compilers and generated file with one million print statements for go and for Nim. Nim dealt with it in 3 minutes, go on the other hand, could not complete compilation at all and after 5 minutes of heat and pain, it crashed due to heap memory overflow.
After all this good talk, you might be wondering, why didn’t I find about this language sooner? (Or maybe you regret the fact you did find out at the end) I honestly do not know. Language itself is kind of old actually (older than rust). It probably just did not get lot of attention due to being independent project, when in comparison, Go or Rust, that are at similar age, got boosted by Google and Firefox. The reason i tried so hard when writing this article, is because i want Nim to get more visible so that it can get more support and improve even more.