This release brings many performance improvements, including a new garbage collector.
In terms of language features, the biggest new feature are the "to be closed" variables. They can be used to ensure that cleanup routines are always called, similarly to RAII in C++ or try-finally blocks.
<close> is equivalent to golang's defer (either can be implemented in terms of the other) except at the block level. imo calling it RAII mostly leads to confusion. One mailing list user recently asked a bunch of questions around using <close> for RAII. They expected RAII to work even for resources that are never bound to a particular type of local variable, for example if one writes do_thing(io.open("foo.txt")), where do_thing is not responsible for closing files because sometimes it is used with files that will continue to be used. They eventually concluded that the closest thing to RAII available was __gc.
Some users presented separate complaints about resources kept in to-be-closed locals in coroutines not necessarily being closed. You can do something to try to solve this, like setting the __gc and __close metamethods of coroutines to call coroutine.close. A "real" solution would look more like dynamic-wind. Notably golang doesn't attempt to solve this one, so maybe not solving it is fine.
I wasn't deeply familiar with python's `with`, so I looked it up[0]
<close> differs from `with` in at least the sense that it doesn't have any equivalent to __enter__ and doesn't create its own block. It creates a local variable whose __close metamethod will be called when it goes out of scope. Since Lua has lexical scope at the block level rather than the function level, this works similarly to the way Python calls __exit__.
These snippets of Python and Lua are roughly equivalent. They both open a file, read one line, and close it, or do nothing if there was some error opening the file.
try:
with open("foo.txt") as f:
print(f.readline())
# f is now closed.
except:
pass
local f,err = io.open("foo.txt")
if not err then
local f <close> = f
print(f:read("*l"))
end
-- f is now closed.
C#'s `using`[1] seems much closer, except that it handles nulls by not trying to close them and lua's <close> does not include any such handling.
In terms of language features, the biggest new feature are the "to be closed" variables. They can be used to ensure that cleanup routines are always called, similarly to RAII in C++ or try-finally blocks.