Hello,
I was looking into creating genuine ref types with finalisers. Is there a way to attach a finalizer to a type without using new(...) ?
It seems that Nim is attaching a finaliser statically, but only does that if new() is mentioned somewhere in the program. This is what I found to be working so far, but I feel stupid doing it:
type
MyObj = ref object of RootObj
s: string
count: int
proc finalize(self:MyObj) =
echo "Destroying ", self.s
if false:
var x:MyObj; new(x, finalize)
proc newMyObj(s:string = "") : MyObj =
result = MyObj(s:s, count:0)
Would it make sense perhaps to either repurpose `=destroy` or add proc `=finalize`(self: MyRefObj) ?
Thanks, George.
Here you go, requires nim version 1.0: https://play.nim-lang.org/#ix=1Yu9
With the new destructors system, the compiler can seamlessly convert destructors to finalizer.
Though this technically does it, it doesn't seem to be more elegant though, as it relies on having two types? (thus declaring members for one, then using another one for instantiation)
Granted, finalisers most often are required for internal types that do not refer external OS structures, but still.
The inner type of a ref|ptr object is a valid type. Perhaps you'll find one of these more elegant.
template deref(T: typedesc[ref|ptr]): typedesc =
typeof(default(T)[])
proc `=destroy`(self: var deref(MyRef)) = discard
macro finalizer*(fn: untyped): untyped =
let ref_typ = fn.params[1][1]
fn.params[1][1] = nnkVarTy.newTree(quote do: typeof(default(`ref_typ`)[]))
result = fn
proc `=destroy`(self: MyRef) {.finalizer.} = discard