A few programmers of us who are doing c++ and now work in Java have a big problem, because Java does not and will not implement the c++ like destructor logic. Therefore, we began to study the Fantom and think that this language has the greatest chance for doing it! Our basic question is: Is there a plan for the destructor implementation in the Fantom language?
We are ready to help in any kind of implementation logic as long as suitable plugin for Fantom will be operational. (We tried NB, Eclipse, IntelliJ, ...)
Regards from Belgrade, Serbia Vladimir Kokovic, Dragan Ciric
alexlamslThu 29 Jul 2010
Would you mind explaining the difference between your proposed destructor and java.lang.Object.finalize?
vladakkThu 29 Jul 2010
The destructor method fulfills the opposite to constructor method functionality. It is automatically called when its scope of existence has finished (for example, if it was defined as a local object within a function and the function ends)
Regards from Belgrade, Serbia, Vladimir Kokovic, Dragan Ciric
jodastephenThu 29 Jul 2010
So what you want is the compiler to auto-generate a call to the destructor method as the variable goes out of scope?
// Fantom code
{
person := Person()
// do something
}
// compiled to equivalent Java code (compilation actually goes to fcode then bytecode)
{
Person person = new Person()
// do something
person.destructor()
}
Personally, I've never needed such a concept, so wouldn't be entusiastic at adding it. However, I'd love to hear your use case for why it is so necessary.
vkSQLbeginTrans myBET;
// do something
// if some exception occurred then destructor will call rollback !!!
myBET.commit();
}
This is rock solid and simple code!
Regards from Belgrade, Serbia, Vladimir Kokovic, Dragan Ciric
katoxThu 29 Jul 2010
In Fantom (as in Java) there are no local objects (stack allocated). Everything is allocated on heap (equivalent of Fred* p = new Fred(); /* ...*/ delete p;). Even in C++ there would be no automatic destructor call at the end of the declaring scope in such a case (it can be done only manually and that would cause double delete bug later).
In Fantom (and in Java) all objects might live well outside declaration scope and cease to exist only when the garbage collector found no references on them. That is the point when finalize() would be called in Java. However this might not ever happen (unless the app is shut down) so it is not that useful and that's why Fantom Obj type has no such method.
If you added automatic destructor calls at the end of the declaring scope you have to be sure that constructed objects couldn't be referenced later. Otherwise this classic C++ situation could happen (in Fantom syntax):
class A {
Fred[] freds := Fred[,]
Void foo()
{
fred := Fred() // construct a local variable
fred.use()
freds.add(fred)
fred.destructor() // this would be the automatic destructor call
// fred is now uninitialized
}
Void bar()
{
fred := freds.get(0) // retrieve a reference
fred.use // BOOOM! Used an uninitialized object!
}
static Void main() {
a := A()
a.foo
b.foo // oops!
}
}
Checking for possible reference leaks to any objects created would be incredibly expensive. With GC in mind it is always better to utilize try-catch-finally or some sort of eventing to achieve the same effect.
andyThu 29 Jul 2010
You probably want some similar to C#'s IDisposable and using statements:
using (res = SomeResource())
{
// do stuff with res
} // res.dispose automatically called at end of scope
I believe dispose is called also in the event of an exception - so its basically just syntax sugar for a try-catch-finally - so there is still a responsibility on the developer to use it correctly.
vladakkThu 29 Jul 2010
We are not talking about object destroy. We need only automatic call for some method at scope end.
Regards from Belgrade, Serbia, Vladimir Kokovic, Dragan Ciric
heliumThu 29 Jul 2010
C++ like destructors don't work well in a language that has closures (like Fantom) as any variable could possibly get captured and thus its life would be extended.
To solve your transaction problem you can use first class functions to your advantage. You have a beginTransaction function that takes another function as argument. The function starts a transaction, executes the passed function inside a try-catch block and commits the transaction when no exception was thrown and aborts it otherwise (alternately you could let the passed in function return a success/failure value depending on which the transaction gets committed or aborted respectively).
beginTransaction |->| {
... // the transactional code
}
This would have the same effect as your C++ code
{
vkSQLbeginTrans foo;
... // the transactional code
foo.commit();
}
but looks cleaner and is more concise.
tacticsThu 29 Jul 2010
The destructor method fulfills the opposite to constructor method functionality. It is automatically called when its scope of existence has finished (for example, if it was defined as a local object within a function and the function ends)
If I remember correctly, there's no efficient procedure for doing this. The best you can get are approximations, meaning you can't guarantee the destructor is always called.
brianFri 30 Jul 2010
Just to re-iterate what I think has already been summed up:
C++ destructors as used for memory management don't really apply to JVM which has GC
C++ notion of scope based on stack allocated variables doesn't really apply to the JVM since everything is heap allocated and doesn't apply to Fantom really well since features like closures don't cleanly fit into stack scope
the the Java world, code to force cleanup of a resource is best done in a finally block
in Fantom we can hide the setup/cleanup behind a method really elegantly with closures
vladakkMon 2 Aug 2010
After all, can we ask the question: Is there a chance that the compiler generate a call for some method at the moment of variable scope end?
heliumMon 2 Aug 2010
Where exactly does the scope of a variable end that got captured by a closure?
Thank you helium, we have completely forgotten about the D language. In our opinion, Fantom could accept both ideas from the D language!
brianMon 2 Aug 2010
The core feature to handle these cases is try/finally blocks.
The scope feature in D looks cool (don't remember seeing that before when perusing D).
Essentially use of closures, D scope, C# using blocks are all syntax sugar for making finally easier to read since it tends to obscure code. What we have said in the past was that if we didn't have "control block closures" that we would consider adding something like C# using blocks (or maybe D like scopes). The final result of the closure design was it-blocks which sort of can be used by control blocks, but we might still want to consider other sugar (probably not for 1.0, but for 1.1).
vladakk Thu 29 Jul 2010
A few programmers of us who are doing c++ and now work in Java have a big problem, because Java does not and will not implement the c++ like destructor logic. Therefore, we began to study the Fantom and think that this language has the greatest chance for doing it! Our basic question is: Is there a plan for the destructor implementation in the Fantom language?
We are ready to help in any kind of implementation logic as long as suitable plugin for Fantom will be operational. (We tried NB, Eclipse, IntelliJ, ...)
Regards from Belgrade, Serbia Vladimir Kokovic, Dragan Ciric
alexlamsl Thu 29 Jul 2010
Would you mind explaining the difference between your proposed destructor and
java.lang.Object.finalize
?vladakk Thu 29 Jul 2010
The destructor method fulfills the opposite to constructor method functionality. It is automatically called when its scope of existence has finished (for example, if it was defined as a local object within a function and the function ends)
Regards from Belgrade, Serbia, Vladimir Kokovic, Dragan Ciric
jodastephen Thu 29 Jul 2010
So what you want is the compiler to auto-generate a call to the destructor method as the variable goes out of scope?
Personally, I've never needed such a concept, so wouldn't be entusiastic at adding it. However, I'd love to hear your use case for why it is so necessary.
vladakk Thu 29 Jul 2010
Yes, your code is correct.
Consider this c++ class:
class vkSQLbeginTrans {
};
and usage of this class:
{
}
This is rock solid and simple code!
Regards from Belgrade, Serbia, Vladimir Kokovic, Dragan Ciric
katox Thu 29 Jul 2010
In Fantom (as in Java) there are no local objects (stack allocated). Everything is allocated on heap (equivalent of
Fred* p = new Fred(); /* ...*/ delete p;
). Even in C++ there would be no automatic destructor call at the end of the declaring scope in such a case (it can be done only manually and that would cause double delete bug later).In Fantom (and in Java) all objects might live well outside declaration scope and cease to exist only when the garbage collector found no references on them. That is the point when
finalize()
would be called in Java. However this might not ever happen (unless the app is shut down) so it is not that useful and that's why FantomObj
type has no such method.If you added automatic destructor calls at the end of the declaring scope you have to be sure that constructed objects couldn't be referenced later. Otherwise this classic C++ situation could happen (in Fantom syntax):
Checking for possible reference leaks to any objects created would be incredibly expensive. With GC in mind it is always better to utilize
try-catch-finally
or some sort of eventing to achieve the same effect.andy Thu 29 Jul 2010
You probably want some similar to C#'s
IDisposable
andusing
statements:I believe
dispose
is called also in the event of an exception - so its basically just syntax sugar for atry-catch-finally
- so there is still a responsibility on the developer to use it correctly.vladakk Thu 29 Jul 2010
We are not talking about
object destroy
. We need only automatic call for some method at scope end.Regards from Belgrade, Serbia, Vladimir Kokovic, Dragan Ciric
helium Thu 29 Jul 2010
C++ like destructors don't work well in a language that has closures (like Fantom) as any variable could possibly get captured and thus its life would be extended.
To solve your transaction problem you can use first class functions to your advantage. You have a
beginTransaction
function that takes another function as argument. The function starts a transaction, executes the passed function inside a try-catch block and commits the transaction when no exception was thrown and aborts it otherwise (alternately you could let the passed in function return a success/failure value depending on which the transaction gets committed or aborted respectively).This would have the same effect as your C++ code
but looks cleaner and is more concise.
tactics Thu 29 Jul 2010
This is called escape analysis.
If I remember correctly, there's no efficient procedure for doing this. The best you can get are approximations, meaning you can't guarantee the destructor is always called.
brian Fri 30 Jul 2010
Just to re-iterate what I think has already been summed up:
vladakk Mon 2 Aug 2010
After all, can we ask the question: Is there a chance that the compiler generate a call for some method at the moment of variable scope end?
helium Mon 2 Aug 2010
Where exactly does the scope of a variable end that got captured by a closure?
Perhaps you want something like the 'scope' keyword from D?
vladakk Mon 2 Aug 2010
Thank you
helium
, we have completely forgotten about the D language. In our opinion, Fantom could accept both ideas from the D language!brian Mon 2 Aug 2010
The core feature to handle these cases is try/finally blocks.
The scope feature in D looks cool (don't remember seeing that before when perusing D).
Essentially use of closures, D scope, C# using blocks are all syntax sugar for making finally easier to read since it tends to obscure code. What we have said in the past was that if we didn't have "control block closures" that we would consider adding something like C# using blocks (or maybe D like scopes). The final result of the closure design was it-blocks which sort of can be used by control blocks, but we might still want to consider other sugar (probably not for 1.0, but for 1.1).