diff --git a/content/objects.md b/content/objects.md index 1d87460..b999be5 100644 --- a/content/objects.md +++ b/content/objects.md @@ -8,59 +8,63 @@ In Nimrod, objects are like structs from C family languages and define a groupin ``` nimrod type Animal* = object - name*, genus*, species*: string - age: int # Not exported - PAnimal* = ref Animal + name*, species*: string + age: int proc sleep*(a: var Animal) = a.age += 1 -# create a new Animal, mutable and not on the heap -var carl = Animal(name : "Carl", - genus : "Lama", - species : "glama", - age : 12) +proc dead*(a: Animal): bool = + result = a.age > 20 + +var carl: Animal +carl = Animal(name : "Carl", + species : "L. glama", + age : 12) -# create a new Animal, immutable and not on the heap let joe = Animal(name : "Joe", - genus : "Homo", - species : "sapiens", + species : "H. sapiens", age : 23) -when false: - # Will not compile, Joe's value is immutable - joe.age = 57 +assert not carl.dead +for i in 0..10: + carl.sleep() +assert carl.dead +``` -# Allocate an Animal on the heap +Object types are declared in a type section, as usual. They can be exported, and individual fields can also be exported. Fields can be safely exported without violating encapsulation because call syntax is equivalent between them. + +Initially, `carl` is created on the stack and initialized to zeros, so its value is `[name = nil, species = nil, age = 0]`. It is mutable, so that means that the contents of `carl` can be changed. This also means it can be passed to functions that require a variable parameter, like `sleep()`, which can modify its value. + +`joe` is also created on the stack, but it's contents are immutable and can not be changed. Attempting to do so, say through `joe.age = 57`, will fail with an error at compile time. + +``` nimrod let mittens: ref Animal = new(Animal) -# Fill out all the fields, the start out as 0's + mittens.name = "Mittens" -mittens.genus = "Panthera" -mittens.species = "leo" +mittens.species = "P. leo" mittens.age = 6 -# This also goes on the heap since PAnimal is a reference type. -# Initialization is much nicer this way +mittens.sleep() +``` + +`mittens` is a reference to an object allocated on the heap. The value of `mittens` cannot be changed, so `mittens` can never point to anything else, but the value that `mittens` is pointing at can and is changed from the default initialization value of zeros. It's mutability also means that `mittens` can be passed to functions that require a variable parameter. + +You might ask whether there is a more concise way of initializing reference types, and there is if you give the reference type a name: + +``` nimrod +type + PAnimal* = ref Animal + let spot = PAnimal(name: "Spot", - genus: "Canis", - species: "lupus", + species: "C. lupus", age: 1) +``` -# Same as before, only pointer value is unchangeable -# Pointee is modifiable -spot.age = 2 +In many cases it is only wanted to have the object be a reference type, which is possible by declaring it as a `ref object`. -# Carl is copied, not a reference to Steve -var steve = carl -steve.name = "Steve" -# Carl's name is still "Carl" -assert carl.name == "Carl" -assert steve.name == "Steve" - -# Value of the pointer is copied -let lucy = spot -lucy.name = "Lucy" -# Spot's name is now "Lucy"! -assert spot.name == "Lucy" -assert lucy.name == "Lucy" +``` nimrod +type + Thing* = ref object + positionX*, positionY*: int ``` \ No newline at end of file