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