Jules Jacobs
Posts: 119
Nickname: jules2
Registered: Mar, 2006
|
|
Re: An Alternative to Closure Conversion and to Restricted Closures
|
Posted: Jan 7, 2008 1:42 PM
|
|
> I am using closure conversion as used by Neal Gafter et > al. in their language proposal: > http://www.javac.info/closures-v05.html > [...] > See reply to Neal's post - after this one
I see. The term is already in use: http://en.wikipedia.org/wiki/Closure_conversion so if Neal wants to prevent confusion he has to choose another name.
> I am trying to make it less of a hack by proposing that it > behaves more like an inner class
That's great, but the feature of converting an anonymous function to a class with one method automatically "renames" the invoke method is still there, right? This isn't going to interact well with inheritance.
> That works for some cases, but what about multiple > threads, what about storing the closures in a data > structure, what about: > > static { => void } makeMethod() { > return { => > ... > return { => ...; }; // Error not caught by the > the compiler! Returns from makeMethod and the closure > }; > } > > static void main( String[] notUsed ) { > makeMethod().invoke(); } > > The correct code for the above example is: > > static { => void } makeMethod() { > return { => > ... > { => ...; } // Error not caught by the compiler! > ler! Returns from makeMethod and the closure > }; > } > > But I think it will be common mistake to put return in > because you use return everywhere in Java.
Ok, there are two related issues here:
1) Programmers inserting a return statement because they're used to in inner classes. 2) Returning from a function that has already returned.
I don't think that number 1 is a problem because the syntax for anonymous functions is so different. It might happen 1-2 times and then you know you don't need a return unless you're doing something special.
Number 2 is more interesting. I think the right solution is to just throw a runtime exception, because this is the most expressive. It's possible to analyze statically if the return is wrong (i.e. return from a function that's no longer active), but this is not easy, and you will lose some expressiveness no matter how good your static analysis is. In your example, how are you going to tell that Collections.each doesn't store the anonymous function in a datastructure? There are (complicated) ways to determine this, but you will have to break down abstraction barriers: the caller has to know how the callee is implemented (for example, it has to know if the callee stores the closure in a data structure). And other problems appear: sometimes it *is* correct to store such a closure in a data structure, you just shouldn't call it after the enclosing function has returned. For example:
int foo(){
Bar x = new Bar();
x.setQ({z => return z;});
x.callQ(3);
}
This is more common than you might think. For example, if you want to loop over two collections with the same loop body you want to be able to store a closure in a local variable and call:
collection1.each(theClosure);
collection2.each(theClosure);
For example if you want to determine if some element is present in collection1 or in collection2:
theClosure = {x => if(x==theElement){return true}};
It's quite possible that I am misunderstanding you entirely, I am sure that because you have written a proposal you have thought about this already.
p.s. An alternative solution is to *allow* non local returns, and revert control flow back into the enclosing function if you call the anonymous function. This is possible and it resembles continuations. Sadly it's unfeasible for Java.
|
|