Welcome

This is my personal webpage, were I will put up anything that seems relevant to me at whatever point in time it may be. It is created using a tool of my own making called dtt which is a work in progress. As such the site may change appearance from time to time as the tool evolves.

Most of the content on this page will be sporadic blog posts.

Why I like nim

Why I like the Nim programming language

There are two main reasons why I like the Nim programming language and those are A) I'm secretly a bit of a hipster, and B) it's just damned neat.

For the first point it's this thing I have where I kinda drift towards the lesser known road just because it's the lesser known road. Why run Manjaro when you can run Void Linux? Why use Vim when you can use NeoVim? Why use Rust when you can use Nim? It's silly, but there it is.

The second point is the real reason I go with Nim in particular since there's a whole host of programming languages that aren't the hot new thing at the moment that I could've been using instead of Nim.

Nim is just really neat

Nim isn't another take on JavaScript. It's not another C-but-better-or-at-least-different. It's not a JVM-based language that tries to copy a functional language.

It's it's own thing and I like that about it. Of course it draws on previous languages and you can see where it's coming from, but it's sufficiently different that it stands out among other languages.

If you asked me what it's one killer feature is I don't know that I could give you an answer off the top of my head, except that it's not so much about that one feature but the sum of its parts that I find attractive. I like significant whitespace as a concept, I like that it's properly multi-paradigm, I like that it's compiled and statically typed, I like that it's safe but lets you dig into the hairy stuff, I like the syntax and the idioms. None of that is unique to Nim but I think that it has the perfect mix of all of those things (and more).

One thing I do think it does better than many other languages is being multi-paradigm.

Code your own way

Some languages are very opinionated about how you should code in them, some flat out won't let you write code in the "wrong" way, some make it really painful to do so. That's not what Nim does. Nim kind of goes out of its way to let you write code to fit your current problem or your way of reasoning about code.

It also lets you seamlessly move from one paradigm to another without making a big fuss about it.

It supports procedural, functional, object-oriented, and spaghetti-code equally well. It doesn't force you to write code a certain way, you can code entirely without objects or you can construct elaborate object hierarchies if that's what your heart desires.

In doing this it also enables the Goldilocks paradigm: just the right amount of whatever paradigm to make your code clean and elegant.

Typically in my experience that's a little bit of OOP glued together with a bunch of functional and procedural code. Due to supporting Uniform Function Call Syntax (UFCS) Nim will let you write code that stylistically is interchangeable with OOP but is much simpler in reality.

type
  Animal = object
    sound: string

let
  dog = Animal(sound: "woof")
  cat = Animal(sound: "meow")
  bird = Animal(sound: "chirp")

func speak(a: Animal): string =
  return a.sound

for a in @[dog, cat, bird]:
  # These are all equivalent ways of calling `speak()` on `a`
  echo speak(a)
  echo a.speak()
  echo a.speak
  echo speak a

I didn't make any class hierarchies, I didn't overload any methods, there's no virtual methods or abstract interfaces or any trickery going on. I made some Animal objects, a function (func in Nim is syntax sugar for a procedure that has no side-effect, enforced by the compiler), and I simply iterated through my sequence of animals calling my function on each animal in turn.

It's 17 lines long including four different ways of calling the speak function, and the minimal C# example I tried to put together right now was 30 lines long. I know toy examples aren't saying much about real programs, but I think the Nim version is very readable and elegant and it stays like that even as you scale your program up. You write just what you need to solve your problem instead of jumping through hoops to fit your solution into the paradigm proscribed by your language.

You can also scale the Nim example upwards very easily, and callers of your code will be unaffected. Let's say you want a class hierarchy after all:

type
  # The {.inheritable.} pragma is needed to enable inheritance
  # and the objects are made into references so they aren't cast into
  # the base Animal type inside the animals sequence
  Animal {.inheritable.} = ref object
    sound: string
    age: int

  Cat = ref object of Animal
    lives: int

  Dog = ref object of Animal
    yearMultiplier: int

let
  dog = Dog(age: 2, yearMultiplier: 7)
  cat = Cat(age: 4, lives: 9)
  bird = Animal(age: 8)
  animals: seq[Animal] = @[dog, cat, bird]

method age(a: Animal): int {.base.} =
  return a.age

method age(a: Dog): int =
  return a.age * a.yearMultiplier

for a in animals:
  echo age(a) # outputs 14, 4, 8

So now we're up to 25 lines here, but we've got a base class, two subclasses, one base method and an overloaded method as well as some comments. As you can see we could go from a very simple object and a pure function call and then build up an object hierarchy, and in our calling code we didn't change anything at all really.

(Note: This is not strictly true; since we shadowed the age attribute with a method with the same name we have to disambiguate this by calling age(a) rather than a.age(). Using better names for things avoids this issue.)

This quality is one I really appreciate in a programming language and it's why Nim is currently my favourite language to work with.