Skip to content

Instantly share code, notes, and snippets.

@ZoomTen
Last active February 15, 2025 18:44
Show Gist options
  • Save ZoomTen/98332bf74cb0082378557cc3bc96482a to your computer and use it in GitHub Desktop.
Save ZoomTen/98332bf74cb0082378557cc3bc96482a to your computer and use it in GitHub Desktop.
The thing Nim tries to warn me about when using closures
proc b(x: ptr seq[int]): auto =
proc a(): seq[int] =
x[].add(10)
return x[]
a
proc ax(): auto =
# allocate a sequence manually
# will be GC'd at the first opportunity
var k = @[1, 2, 3]
# pass its pointer to the crasherinator
let m = b(k.addr)
echo m()
echo m()
echo m()
echo m()
echo m()
echo m()
m
# k is deleted here, but we return a
# closure that still holds its reference
proc ll(): auto =
let p = ax()
# k is deleted, but the closure env still
# holds a reference to it
echo p()
echo p()
echo p()
echo p()
echo p()
p
let k = ll()
# boom
echo k()
echo k()
echo k()
echo k()
echo k()
echo k()
proc a(x: ref seq[int]): auto =
# nim knows this ref is still used
# when this is invoked, and so is
# still valid (i think)
proc b(): seq[int] =
x[].add(10)
return x[]
b
proc ax(): auto =
# create an intentional reference to a sequence
# will be GC'd properly
let k = new seq[int]
# populate this sequence manually
k[].add(1)
k[].add(2)
k[].add(3)
# before passing it to the crasherinator
let m = a(k)
echo m()
echo m()
echo m()
echo m()
echo m()
echo m()
m
# a reference to k still exists in the closure
# won't be deleted yet because it's a ref
proc ll(): auto =
let p = ax()
echo p()
echo p()
echo p()
echo p()
echo p()
p
let k = ll()
echo k()
echo k()
echo k()
echo k()
echo k()
echo k()
# no crash here!
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment