A yield does not exit the current block, so finalization won't result.
[...]
> And you cannot "not close" the file, because the thread might never be resumed.
In that case, the usual garbage collection will occur.
> This shows there is no universal solution to the problem.
By the same token, one could say that a program can just block infinitely, in which case garbage collection won't happen at all. Does that negate the usefulness of garbage collection? In my opinion, blocks-scope finalization addresses a large class of design patterns, giving the programmer simple declarative language constructs instead of hopefully bug-free code and comments that hopefully describe the intent [1]. It does not free the programmer from the need to have a sound design.
-- close everything
cur:close() -- already closed because all the result set was consumed
con:close()
env:close()
Can one be sure just by looking at this code that it really does what it should? Or perhaps we have forgotten something? And why do we still try to close something that is commented to have already been closed?
In fact, it can easily be seen that the program is not entirely correct, because it has a number of assert() calls that may raise errors and the epilogue won't be reached, leaving certain things not closed. Try to correct that program so that it always closes everything; then what I meant by "unwieldy" will be immediately evident. And that is just a "basic use" example, not a real-world program.