why unrestricted closures are always void?

Mark Mahieu mark at twistedbanana.demon.co.uk
Sat Nov 15 18:53:05 PST 2008


For your amusement...

Several months ago I realised that it's possible to use Neal's  
closures prototype to get code like the following to work:

for each (Employee empl : findEmployees())
     where (empl.yearsInService() > 5)
     orderBy (empl.getLastName()) {

	// do something with empl
}

In this example, it's the control invocation syntax which allows the  
chaining of several 'clauses' into a more sophisticated statement,  
with the 'arguments' to the 'where' and 'orderBy' clauses actually  
being closures which are evaluated on each iteration.

There are caveats to doing this with BGGA as it stands, but exploring  
the idea further I came to the conclusion that the technique could  
form the basis for another language feature, which would allow the  
creation of many different types of 'internal DSL' in Java.

I even started working on a spec for such a language feature, with  
the intention of following up with an implementation (just for my own  
amusement really, I don't see any chance of something like that  
ending up in Java).

One of the more interesting problems to solve relates directly to  
your examples, since many DSLs are best expressed in a form which  
returns a value.  For example, rephrasing the above example in a more  
LINQ-like style would allow the query (the each...where...orderBy  
part) to be assigned to something like an Iterable<Employee>, which  
could then be reused, passed around etc.  As you've noted, that's not  
possible when using the control invocation syntax.

It's a fun one to think about.

Regards,

Mark


On 16 Nov 2008, at 01:21, Vladimir Kirichenko wrote:

> Zdenek Tronicek wrote:
>> Neal, he means control invocation syntax. For example:
>
> Yeah. In ruby which have similar facility I can write something like:
>
> def _for(x, &f) yield x end
>
> and than invoke it:
>
> res = _for(5) do |x| x*2 end
>
> It will be good thing to have ability to write control abstractions  
> those could return results, i.e.:
>
> Iterable<Integer> squares = yield(int i : someIterable()) { i * i }
>
> will construct generator - similar to one that exists in bunch of  
> other languages.
>
> And it's just looks very strange:
>
> //compiles fine
> public static int f(int i, {int ==> int} block) { return  
> block.invoke(i); }
>
> //does fine
> System.out.println(f(3, {int i ==> i*i }));
>
> but:
>
> f(int i : 3) { return i * i; }
>
> reports error:
>
> cannot return a value from method whose result type is void
>            f(int i : 3) { return i * i; }
>
> It's not void neither in closure nor in method.
>
> -- 
> Best Regards,
> Vladimir Kirichenko
>




More information about the closures-dev mailing list