How can I get a reference to the field in this example?
type
Test = object
ok: seq[int]
proc getOk(x: Test): seq[int] =
x.ok
var x = Test(ok: @[])
var ok = x.getOk()
ok.add(3)
echo x.ok
Instead of printing
@[3]
it prints
@[]
because the var statement apparently copies the value. How can I get a reference instead?
Yes, the var statement copies the value.
The following code will result in @[3] being printed:
type
Test = object
ok: seq[int]
proc getOk(x: var Test): var seq[int] =
x.ok
var x = Test(ok: @[])
x.getOk().add(3)
echo x.ok
I made 2 changes to your code:
Does this answer your question?
type
Test = object
ok: seq[int]
proc getOk(x: var Test): ptr seq[int] = addr x.ok
var x = Test(ok: @[])
var ok = x.getOk()
ok[].add(3)
echo x.ok
type
Test = object
ok: ref seq[int]
proc getOk(x: Test): ref seq[int] = x.ok
proc newTest: Test =
new result.ok
result.ok[] = @[]
var x = newTest()
var ok = x.getOk()
ok[].add(3)
echo x.ok[]
Isn't the second version of @def also possible just like this:
type
Test = object
ok: ref seq[int]
proc newTest: Test =
result.ok = new seq[int]
result.ok[] = @[]
var x = newTest()
var ok = x.ok
ok[].add(3)
echo x.ok[]
Isn't the second version of @def also possible just like this:
Right, thanks. Don't even need the getOk() proc anymore.
Are there any major drawbacks of using a ptr, anything I should know?
When the object disappears, the ok's memory will get garbage collected even though you still hold a ptr to it. Your ptr is then invalid and you will get invalid results or a segfault. With a ref the seq will only be garbage collected once no references to it remain.
proc getOk(x: Test): seq[int] =
x.ok
Should creates a sequence but is that "x.ok" the same as "result = x.ok" in this case. And what do we get, a new sequence, or the old from x object? I wonder that it compiles.
Should creates a sequence but is that "x.ok" the same as "result = x.ok" in this case
Yes, the last expression is automatically the result variable.
And what do we get, a new sequence, or the old from x object?
You can't get the same sequence, because that would require x to be var. So a copy has to be made. If you use a var seq[int] return type you will indeed get the same sequence back:
proc getOk(x: var Test): var seq[int] =
x.ok
Try this:
type
Test = object
ok: seq[int]
proc getOk(x: Test): seq[int] =
echo "2: ", repr(x.ok)
result=x.ok
echo "3: ", repr(result)
var x = Test(ok: @[])
echo "1: ", repr(x.ok)
x.ok.add(1)
var ok = x.getOk()
echo "4: ", repr(ok)
ok.add(3)
echo x.ok # @[1]
gives something like this
1: 0x101ee5050[]
2: 0x101ee6050[1]
3: 0x101ee7050[1]
4: 0x101ee7050[1]
@[1]
You can identify where copies are made and where not this way.
EDIT: Added some numbers for the "rep() representations"
Second Example:
type
Test = object
ok: ref seq[int]
proc newTest: Test =
result.ok = new seq[int]
result.ok[] = @[]
var x = newTest()
var ok = x.ok
ok[].add(3)
var y = x
y.ok[].add(1)
echo "1: ", x.ok[].repr()
echo "2: ", y.ok[].repr()
y.ok[].add(2)
proc tryThis(x: Test): ref seq[int] =
echo "3: ", x.ok[].repr()
result = x.ok
echo "4: ", result.repr()
let z = tryThis(x)
z[].add(4)
echo "5: ", z.repr()
echo "6: ", x.ok[].repr()
Gives:
1: 0x103983050[3, 1]
2: 0x103983050[3, 1]
3: 0x103983050[3, 1, 2]
4: ref 0x103981050 --> 0x103983050[3, 1, 2]
5: ref 0x103981050 --> 0x103983050[3, 1, 2, 4]
6: 0x103983050[3, 1, 2, 4]