Objects in Nim use the type constructor:

# Type Definition
type
  MusicTrack = object
    index: int
    title: string

# (Mutable) Value
var summer = MusicTrack(index: 1, title: "Summer in the City")

That reminds me of Records in Reason:

/* Type definition */
type musicTrack = {index: int, title: string}

/* Value */
let summerInTheCity = {index: 1, title: "Summer in the City"}

In Nim, “An object is a value type, which means that when an object is assigned to a new variable all its components are copied as well.” 1

When you call the object constructor with var summer, you create a mutable object on the stack.

type PersonRef = ref object
  id: int
  name: string

let tom = PersonRef(id: 1, name: "Tom")

tom is a reference to an object allocated on the heap. tom is immutable (via the let keyword). You can't change the tom variable.
When you initialize tom, Nim will create the object on the stack with binary zeroes. And although the let keyword makes the variable immutable, you can change the values it is pointing at.
Thus, you can “assign” new values to tom (id of 1 and name of “Tom”). You must do that when you define the new variable (let tom). You can't change it later.

const variables work the same as let, but must be computable at compile time. The main benefit is efficiency, as the compiler can optimize them.

In JavaScript, you might declare a new object literal with a const keyword.

const myCar = {
  make: "Toyota,
  model: "Yaris",
  year: 2005
}

const means that you can't declare a new variable with the same name myCar. This doesn't work:

const myCar = {
  make: "Toyota,
  model: "Yaris",
  year: 2005
}

const myCar = {
  make: "Tesla"
  model: "S",
  year: 2018
}

But you can still change the values inside myCar. The keywords inside the object point to the actual values. And you can change where you point them at.

const myCar = {
  make: "Toyota,
  model: "Yaris",
  year: 2005
}

myCar.make = "Tesla"
myCar
> {make: "Tesla", model: "Yaris", year: 2008, features: Array(2)}

Now you have a Tesla instead of a Toyota!

Reference Types

For Nim:

References (similar to pointers in other programming languages) are a way to introduce many-to-one relationships. This means different references can point to and modify the same location in memory . 2

Now you can create mutually recursive types.

Nim:

type Student = ref object
  taughtBy: ref Teacher

type Teacher = ref object
  students: seq[Student]

Reason 3:

type student = {taughtBy: teacher}
and teacher = {students: list(student)};

If you pass a ref object as an argument to a procedure (function), the procedure can modify it.

Nim encourages composition over inheritance for objects, but you can use inheritance and OOP patterns, see Object Oriented Programming.

Further Reading


  1. https://nim-lang.org/docs/tut1.html#advanced-types-objects ↩︎

  2. https://nim-lang.org/docs/tut1.html#advanced-types-reference-and-pointer-types ↩︎

  3. https://reasonml.github.io/docs/en/more-on-type#mutually-recursive-types ↩︎