How can a closure iterator manage resources? In my particular case, I have a closure iterator that create channels and threads. When the iterator is aborted from the caller side, how can I free the resources I have allocated in the iterator?
For instance, consider the following example: import strutils import os proc stream(m: int): iterator: int = iterator iter: int {.closure.} = var i = 0 echo "Allocate resources" while true: yield i inc(i) if i == m: echo "Iterator max reached; end of iterator" break echo "Deallocate resources" result = iter proc main = let iter = stream(parseInt(paramStr(1))) for i in iter(): echo "i=", i if i == 10: echo "Aborting iteration in main after 10 items..." sleep(2_000) break echo "Out of iterator in main" echo "Before main" main() echo "After main" Run This code creates an iterator that count up to a maximum specified from the command line, but after 10 loops the caller procedure aborts the iterator. If we run it like `./pug 5`, we see that the iterator allocates the resources and frees them when it naturally completes. Before main Allocate resources i=0 i=1 i=2 i=3 i=4 Iterator max reached; end of iterator Deallocate resources Out of iterator in main After main Run But if we run it like `./pug 15`, we see that the deallocation does not happen: Before main Allocate resources i=0 i=1 i=2 i=3 i=4 i=5 i=6 i=7 i=8 i=9 i=10 Aborting iteration in main after 10 items... Out of iterator in main After main Run Enclosing the iterator code with a `try: ... finally: ...` does not help because there are no exceptions in the game. I've looked at the [Nim Destructors and Move Semantics](https://nim-lang.org/docs/destructors.html) documentation but that does not seem to apply there either. So, how do I ensure that resources are freed when a closure iterator is out of scope?