Yesterday I was playing with some OOP stuff, including proCall. While using procCall was working fine in my first tiny example, now for a more complex example with initialization I get a c compiler error. The code below may be similar to Ruby, where we generally define a initialize() method for each class, and call super() to initialize parent class. But I haven't used OOP Ruby in the last few years, so maybe my memory is wrong.
type
Animal* = ref object of RootObj
age*: int
proc init(x: var Animal) =
x.age = 0
method cry(x: Animal) {.base.} =
echo "Animal is silent..."
type Mammal* = ref object of Animal
legs: int
proc init(x: var Mammal) =
x.Animal.init()
x.legs = 4
method cry(x: Mammal) =
echo "Mammal is crying..."
type
Dog* = ref object of Mammal
tail: int
ears: int
proc init(x: var Dog) =
x.Mammal.init()
x.tail = 1
x.ears = 2
proc newDog(): Dog =
new result
result.init
return result
method cry(x: Dog) =
echo "Dog is barking..."
proc birthsday(x: var Dog) =
inc(x.age)
type
Cat* = ref object of Mammal
tail: int
ears: int
angry: bool
proc init(x: var Cat) =
x.Mammal.init()
x.tail = 1
x.ears = 2
x.angry = false
proc newCat(): Cat =
new result
result.init
return result
method cry(x: Cat) =
if x.angry:
echo "Cat says: Grrr..."
else:
echo "Cat says: Mmm.."
proc main =
var s = newSeq[Animal]()
let c = newCat()
c.angry = true
s.add(c)
s.add(newDog())
Dog(s[1]).birthsday()
for a in s:
a.cry()
echo "Age: ", a.age
if a of Dog:
echo "A dog with ", Dog(a). tail, "tails"
main()
$ nim c t.nim
Hint: used config file '/home/stefan/Nim/config/nim.cfg' [Conf]
Hint: system [Processing]
Hint: t [Processing]
CC: t
Error: execution of an external compiler program 'gcc -c -w -I/home/stefan/Nim/lib -o /tmp/stefan/.cache/nim/t_d/t.c.o /tmp/stefan/.cache/nim/t_d/t.c' failed with exit code: 1
/tmp/stefan/.cache/nim/t_d/t.c: In function ‘init_hPQB9bncQO33ZGcoMQdkBKg’:
/tmp/stefan/.cache/nim/t_d/t.c:370:10: error: ‘*x’ is a pointer; did you mean to use ‘->’?
T1_ = &x->Sup;
^~
->
/tmp/stefan/.cache/nim/t_d/t.c: In function ‘init_mSSvrmRS9bt4Nq6vrZQpYQQ’:
/tmp/stefan/.cache/nim/t_d/t.c:382:10: error: ‘*x’ is a pointer; did you mean to use ‘->’?
T1_ = &x->Sup;
^~
->
/tmp/stefan/.cache/nim/t_d/t.c: In function ‘init_WBRfKYrhvEwtbXboHZJTMQ’:
/tmp/stefan/.cache/nim/t_d/t.c:486:10: error: ‘*x’ is a pointer; did you mean to use ‘->’?
T1_ = &x->Sup;
^~
->
/tmp/stefan/.cache/nim/t_d/t.c: In function ‘main_r7VpEd9b9aQPUbk4pk8k4iZQ’:
/tmp/stefan/.cache/nim/t_d/t.c:615:37: error: lvalue required as unary ‘&’ operand
birthsday_WBRfKYrhvEwtbXboHZJTMQ_2(&((tyObject_DogcolonObjectType__9aSs3XCzg3yD8YNUmflsgKw*) (s->data[((NI) 1)])));
$ nim -v
Nim Compiler Version 0.18.1 [Linux: amd64]
Compiled at 2018-09-14
Copyright (c) 2006-2018 by Andreas Rumpf
git hash: 382fe446c3926f7976de09b7a1d8ad131912c7b6
active boot switches: -d:release
I have already encountered this error. As far as I remember, it occurs when you use "var" in a proc whereas the type is a "ref object". If you change this in your example, the error disappears.
type
Animal* = ref object of RootObj
age*: int
proc init(x: Animal) =
x.age = 0
method cry(x: Animal) {.base.} =
echo "Animal is silent..."
type Mammal* = ref object of Animal
legs: int
proc init(x: Mammal) =
x.Animal.init()
x.legs = 4
method cry(x: Mammal) =
echo "Mammal is crying..."
type
Dog* = ref object of Mammal
tail: int
ears: int
proc init(x: Dog) =
x.Mammal.init()
x.tail = 1
x.ears = 2
proc newDog(): Dog =
new result
result.init
return result
method cry(x: Dog) =
echo "Dog is barking..."
proc birthsday(x: Dog) =
inc(x.age)
type
Cat* = ref object of Mammal
tail: int
ears: int
angry: bool
proc init(x: Cat) =
x.Mammal.init()
x.tail = 1
x.ears = 2
x.angry = false
proc newCat(): Cat =
new result
result.init
return result
method cry(x: Cat) =
if x.angry:
echo "Cat says: Grrr..."
else:
echo "Cat says: Mmm.."
proc main =
var s = newSeq[Animal]()
let c = newCat()
c.angry = true
s.add(c)
s.add(newDog())
Dog(s[1]).birthsday()
for a in s:
a.cry()
echo "Age: ", a.age
if a of Dog:
echo "A dog with ", Dog(a). tail, "tails"
main()
I find this error very annoying as it is not easy to find the cause. And, event if "var" is not needed here, this is nevertheless a valid construct.
Yes, without var it works fine.
For a init proc using var feels natural for me, indeed I had the wrong feeling that it may be even necessary to modify member fields. But var is only needed to modify the ref itself, which is not desired of course.
Funny typo in my code:
echo "A dog with ", Dog(a). tail, "tails"
There is an unwanted space between period and tail. I am surprised that that compiles.