Is there a way to return a pointer to constant in Nim? For example:
type
Thingy = object
x*: int
OwnsThingy = object
t: ptr Thingy
proc makeOwnsThingy(): OwnsThingy =
result.tt = cast[ptr Thingy](alloc(Thingy.sizeof))
result.tt.x = 100
# I want to return self.tt as a pointer to a constant.
# Maybe with a syntax like `ptr const Thingy` or `ptr static Thingy`?
proc getInner(self: OwnsThingy): ptr Thingy = self.tt
proc inc(self: var Thingy) = self.x += 1
when isMainModule:
let ot = makeOwnsThingy()
let thing = gets_inner(ht)
thing[].inc() # This should fail because I want thing[] to be a constant
Same thing in C would be const TypeName *ptr_to_the_const_thing;
I was doing this in D by writing out the function signature as const(Thingy)* getInner(OwnsThingy self) { return self.tt; }. Trying to modify the dereferenced value becomes an error. I want to do this in Nim and have it type-checked if possible.
While Nim has no support for const pointers directly, you could easily create a wrapper type that enforces no mutation to happen. But it's not required here and something like
type
Thingy = object
x*: int
OwnsThingy = object
t: ptr Thingy
proc makeOwnsThingy(): OwnsThingy =
result.t = cast[ptr Thingy](alloc(Thingy.sizeof))
result.t.x = 100
# I want to return self.tt as a pointer to a constant.
# Maybe with a syntax like `ptr const Thingy` or `ptr static Thingy`?
proc getInner(self: OwnsThingy): var Thingy = self.t[]
proc inc(self: var Thingy) = self.x += 1
when isMainModule:
let ot = makeOwnsThingy()
let thing = getInner(ot)
thing.inc() # This should fail because I want thing[] to be a constant
does not compile. But there are few reasons to directly go for ptr and alloc in Nim, Nim is not D, our automatic memory management story actually works.
[...] there are few reasons to directly go for ptr and alloc in Nim, Nim is not D.
Agreed, though I'm assuming I have to use ptr for C types.
By the way, is following code contain a bug? I was trying to see if : var Thingy return type returns a reference (or a pointer) but it doesn't seem to do that:
type
Thingy = object
x*: int
OwnsThingy = object
t*: ptr Thingy
proc makeOwnsThingy(): OwnsThingy =
result.t = cast[ptr Thingy](alloc(Thingy.sizeof))
result.t.x = 100
proc getInner(self: OwnsThingy): var Thingy = self.t[]
proc inc(self: var Thingy) = self.x += 1
when isMainModule:
let ot = makeOwnsThingy()
var thing = getInner(ot)
echo ot.t[] # Prints 100
thing.inc()
echo ot.t[] # Prints 100 again, should have printed 101, right?
Edit: Okay, not a bug, but returning a var Thingy introduces a copy, which is not what I wanted.
No, the copy is introduced here var thing = getInner(ot) as var T return values mirror what happens with array access, a named entity is observable and a copy, compare that to var thing = s[i]