Nim! pt8 - Generics

A hotly debated topic, I wanted to dive in and see how they were used in Nim



In my last post on Nim, I tried to figure out the answer to “How do I test in Nim?”. The answer was, basically, create a separate program with a bunch of asserts for each module I want to test. The next thing I decided I should learn about are how Nim implements Generics!

Let’s look at a little snippet of a vector library I’m developing in Nim:

  TVec2*[T] = object
    x*: T
    y*: T

# pretty print the vector
proc `$`*[T](a:TVec2[T]): string =
  result = "(" & $a.x & "," & $a.y & ")"

This code actually illustrates several concepts! First, lets talk about operator overloading. You overload operators by naming a procedure specially, IE with back-ticks around the operator symbol. There are a couple of operators that don’t have overloading implemented (like the assignment operator, =).

The above example demonstrates an operator used to automatically convert a type into a string, very useful when dealing with an unknown generic type.

The brackets and T value ([T]) after TVec2* tells the compiler that when being instantiated, a type T should be specified for TVec2. The * means that the Tvec2 type should be exported for use outside the module. The T value can be used anywhere in the subsequent expression (Ex: y*: T).

This means that the above definition of TVec2 needs to be instantiated something like so:

var vec = TVec2[float](x: 1, y: 1)

Note the [float] after TVec2.

This turns out to be pretty straight forward and scaleable to more than one type being defined generically.

One thing to keep in mind is that the brackets always come after the export symbol (*), if there is one.