[Date Prev][Date Next][Thread Prev][Thread Next]
- Subject: Re: block-scope finalization
- From: Tom Sutcliffe <tomsci@...>
- Date: Thu, 14 Jan 2016 12:38:49 +0000
On 24 Nov 2015, at 4:52 pm, Roberto Ierusalimschy <firstname.lastname@example.org> wrote:
> What is wrong with the following proposal?
> local <some mark to be invented> name = exp
> Unlike a regular 'local' declaration, this one must define only one
> variable and it must be initialized. (Both restrictions could be easily
> removed; they are more about programming style.)
> When the local 'name' goes out of scope, then:
> 1 - if its value is a function, that function is called (no parameters)
> 2 - if its value is a table/userdata, its __close (or some other new
> name) metamethod, if present, is called.
I do like the sound of that. It nicely sidesteps the whole GC-vs-refcounting scoping debate, because it won't be finalising or deallocing the value concerned, only calling its __close metamethod, which really is all I've ever wanted from such a construct. I don't really ever care about deterministically deallocing memory, only about making sure cleanup code can be run when I need it (and if I do need deterministic deallocing, I can write a native-code __close method to do that). I am generally happy with the GC behaviour for all scenarios other than it not offering deterministic cleanup of block-scoped values, and by not having to alter the language's memory management in the slightest this sounds like the best of both worlds.
I've never looked at how C Python implements its hybrid refcount-plus-gc model, so I don't know if it's a horrible mess that we'd never want in a Language like Lua, but I'm not automatically against the concept of a hybrid memory management mechanism. But I think it's a separate issue to what we actually want here which is deterministic cleanup based on variable scope, and we shouldn't confuse the two things. In other words refcounting is one way of achieving that, but clearly not the only way, and Roberto's proposal of extending the upvalue mechanism seems just as good and much cleaner. Indeed I've seem Python code which implicitly *relies* on objects getting refcounted cleanup, which is very fragile, and we don't want to move toward a syntax which relies on a particular memory model implementation.
I'd add one suggestion however, which would be instead of "local <mark> name" there is a new one-word keyword to indicate this special meaning, perhaps "blocklocal name".
Doing this would avoid the sorts of ambiguity/potential for mistakes that C constructs like "char* foo, bar" introduce when more than one variable is declared (written like that you might think that bar was a char* not just a char). Also I've just never liked multi-word types/modifiers like C's "unsigned int". I'd also point to Lua's use of "elseif" rather than "else if" as a previous example of where one token is preferred over two.
I'd suggest also that it might be simpler to not have the requirements that this only takes one variable which must be initialised - since presumably you must still be allowed to reassign to the variable (including assigning it nil) and thus there shouldn't be a requirement that the variable never changes its value during the block scope, it seems a bit confusing to require that it have a value at the start. I assume that only the value which the variable had at scope exit would be the thing that got __close()d? And having a single "blocklocal" keyword makes it clearer that the block-ness applies to every variable declared and avoids even having to document that "local foo, block bar" isn't valid.