convert 'objects' to a more literate style
This commit is contained in:
parent
039abf38fa
commit
5b66cf0b7b
1 changed files with 42 additions and 38 deletions
|
|
@ -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
|
||||||
age : 12)
|
carl = Animal(name : "Carl",
|
||||||
|
species : "L. glama",
|
||||||
|
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"
|
|
||||||
```
|
```
|
||||||
Loading…
Add table
Add a link
Reference in a new issue