convert 'objects' to a more literate style

This commit is contained in:
flaviut 2014-06-19 18:49:55 -04:00
commit 5b66cf0b7b

View file

@ -8,59 +8,63 @@ In Nimrod, objects are like structs from C family languages and define a groupin
``` nimrod ``` nimrod
type type
Animal* = object Animal* = object
name*, genus*, species*: string name*, species*: string
age: int # Not exported age: int
PAnimal* = ref Animal
proc sleep*(a: var Animal) = proc sleep*(a: var Animal) =
a.age += 1 a.age += 1
# create a new Animal, mutable and not on the heap proc dead*(a: Animal): bool =
var carl = Animal(name : "Carl", result = a.age > 20
genus : "Lama",
species : "glama", var carl: Animal
carl = Animal(name : "Carl",
species : "L. glama",
age : 12) age : 12)
# create a new Animal, immutable and not on the heap
let joe = Animal(name : "Joe", let joe = Animal(name : "Joe",
genus : "Homo", species : "H. sapiens",
species : "sapiens",
age : 23) age : 23)
when false: assert not carl.dead
# Will not compile, Joe's value is immutable for i in 0..10:
joe.age = 57 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) let mittens: ref Animal = new(Animal)
# Fill out all the fields, the start out as 0's
mittens.name = "Mittens" mittens.name = "Mittens"
mittens.genus = "Panthera" mittens.species = "P. leo"
mittens.species = "leo"
mittens.age = 6 mittens.age = 6
# This also goes on the heap since PAnimal is a reference type. mittens.sleep()
# Initialization is much nicer this way ```
let spot = PAnimal(name: "Spot",
genus: "Canis", `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.
species: "lupus",
age: 1) 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:
# Same as before, only pointer value is unchangeable ``` nimrod
# Pointee is modifiable type
spot.age = 2 PAnimal* = ref Animal
# Carl is copied, not a reference to Steve let spot = PAnimal(name: "Spot",
var steve = carl species: "C. lupus",
steve.name = "Steve" age: 1)
# Carl's name is still "Carl" ```
assert carl.name == "Carl"
assert steve.name == "Steve" 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`.
# Value of the pointer is copied ``` nimrod
let lucy = spot type
lucy.name = "Lucy" Thing* = ref object
# Spot's name is now "Lucy"! positionX*, positionY*: int
assert spot.name == "Lucy"
assert lucy.name == "Lucy"
``` ```