At the end of the day, closures are function pointers. However, it’s not really clear how already-defined methods on classes could be assigned to a closure. For example, suppose I have the function-type { => double }, and I want to assign to it the method double getVat()?
But suppose it is possible, and I just misunderstood something in the proposal, or it’s just not determined yet and lies somewhere in the blogsphere, currently having a flamewar on it. For this post, I’m making the assumption that it is possible and that the syntax is something like: Function-Type var = ClassName.MethodName.
Let’s move on, then. Remember that a function-type such as { => double } vatGetter would eventually be translated to the following interface:
interface Function12<T> {
T invoke();
}
Function12<? extends Number> vatGetter;
And now let me add to the flame and add another idea: Events through closures. Suppose the { => double } closure would be translated to:
interface Function12<T> {
T invoke();
void addListener(Listener<Function12<T>> listener);
void removeListener(Listener<Function12<T>> listener);
void fireEvent();
}
And the implementation for addListener, removeListener and fireEvent would be made automatic, maybe even via some utility class already in existence. The benefit here is that methods could be responsible for setting off events for their value changes (suppose if the property they’re encapsulating has changed, or if some variable which is used for the internal calculation has changed). This would make implementation of bindings and events in a much smoother way.
Don’t think that this idea is specified only for getter methods: the T will always be the return value of the closure, so that any kind of method could be used. For example, imagine the method double addVat(double price) which adds VAT to a price specified. The closure will be defined as { double => double } and translated into:
interface Function13<T, R> {
T invoke(R p1);
void addListener(Listener<Function13<T>> listener);
void removeListener(Listener<Function13<T>> listener);
void fireEvent();
Which gives us the option to listen to changes in the way VAT is being calculated inside the calcVat method, for example if the value returned by getVat has changed. But, and behold this, since getVat itself can be listened to, we can do the following (in the static constructor, I suppose):
{ => double } vatGetter = VatCalculator.getVat;
{ double => double } vatCalc = VatCalculator.calcVat;
vatGetter.addListener( new Listener... {
vatCalc.fireEvent();
});
Or even a utility method such as Closures.bind(vatGetter, vatCalc). Note that I have no idea how “type-anonymous closures” are referenced, which are needed to define the aforementioned bind method; maybe { ? => ? }, as I’ve seen in the open issues document, but definitely there will be a solution for it.
Now, after binding the two, a setVat method could be implemented as:
void setVat(double v) {
this.vat = v;
getVat.fireEvent();
}
And anyone who is listening on the calcVat method will automatically get an event fired. This could be used to update a UI element, to start some web-service, or to update a database record. The possibilities, as they are with events, are endless - but the implementation can be simple.
Alright, this is all I have to say for the moment, and comments are always a pleasure!
September 24th, 2007 at 10:20 am
[...] Events as a language-feature. This is important, as closures will be (or at least should be) used for events as well, instead of anonymous class implementations of listeners. In C#, events are a language-feature, meaning an event can be defined in a class or interface, delegates could be added to it, and when the event is called (by invocation similar to invoking a delegate), all chained delegates are called. This makes events a lot easier to implement, and prevents a lot of boiler-plate code. I had my own idea on events through closures, but it’s not completely thought through, and obviously not in the closures proposal. [...]
September 24th, 2007 at 5:28 pm
[...] Chaotic Java has been on a tear the last few days with several interesting Java language posts. First up, he blogged about a couple proposals to indicate whether nulls are accepted, and then took on sending events using closures, and C# delegates vs Java closures. All good and interesting stuff worthy of your attention. [...]
September 25th, 2007 at 11:50 am
It’s true - You could do that. What I’m looking for is something inherent in the language, so that everyone could register for events on anything.
If I was to suggest something completely crazy, I would even say that the compiler should bind dependencies by itself - removing the need from a developer to do so.
Since that would require recompilation to make old codebase work, I would otherwise suggest a bytecode transformation agent that does the same.
September 25th, 2007 at 11:52 am
Also, note that in the closures proposal it is mentioned that since the closures are later compiled to interfaces, they can extend other interfaces; this hasn’t manifested itself into an example in the proposal (or I’ve missed it) but it could also bring closures to do what you suggest (extending the basic closure definition, that is).