|Think about Loose Coupling|
Thanks for asking. I'm a zelot on timely destruction, and have been meaning to lobby for not dropping it in Perl 6!
If there is a performance issue, at least make it optional. Objects that need it can have DESTROY called when the last reference is dropped, even if others wait for a central garbage collection scheme or have the code moved outward a few more blocks.
If allocation failure of X for any X triggers a sweep, that's great and addresses the "not everything is memory" issue.
But, here is an example: file is still open so nobody else can open it until it's cleaned up, as opposed to running out of file handles (not going to happen in Windows).
How about a window on the screen? I drop the object and the window doesn't go away until the gc gets around to it! Sure, I can code the close() call myself at the end of the block (and wish I still had real destructors), but that does not work in the face of exceptions. Don't make me put this in a finally block every time; the class should know that and take care of itself.
How about any code that has a "before" and "after" stage, with my code in between. A semaphore is a good example. Building the "after" semantics into the object with language support is a useful tool. The idea of "resource acquisition is initialization" is powerful, and heavily used by C++ programmers. With Perl6 poised to take over the world, don't annoy your potential users like Java did by removing features that they rely on in their other languages.
Ideas: Some classes can be declared with a "needs timely destruction" property. If at least one of these is in a scope, then a gc sweep will be triggered at the end (or finally clause) of that block.
Or, the proper call can be added to the block's finally clause implicitly (Larry showed an explicit way to note this as a property on the declaration of the variable. take that one step further).
Putting in a close() myself or implicitly is going to do it most of the time, but will break down for closures. The compiler can count references; let it do that work for me. But again, the compiler can know when this is never going to happen and emit the simple code. How much of that is part of the low-level Parrot assembly code vs. smarts in the compiler? I think if the compiler could emit code that says "exit scope; if referece count of the variable reached zero, then call function" then it can take it from there.