My lambda leftovers
Maurizio Cimadamore
maurizio.cimadamore at oracle.com
Mon Oct 9 09:02:26 UTC 2017
While I sympathize with the proposal, I think making 'throw' an
expression is trickier than it seems; in Java expression have types - if
we make 'throw' an expression, then we must state what type does it
have. In Scala the Nothing type is used for this purpose; Java doesn't
have such a type. This is evident in cases like this:
<Z> m(Z z) { ... }
m(throw xyz)
So, while I agree this would be a nice-to-have from an usability
perspective, this feature has a cost w.r.t. type system - e.g. it's not
a simple toggle flag on the parser.
Maurizio
On 08/10/17 22:54, Brian Goetz wrote:
> +1.
>
> On 10/6/2017 7:51 AM, Tagir Valeev wrote:
>> Hello!
>>
>> As for throw, I think it should just be converted to an expression,
>> probably of the same type as a null literal (thus throw statement will
>> become an expression statement). In this case it could be useful not
>> only in lambdas, like:
>>
>> return list.isEmpty() ? throw new NoSuchElementException() :
>> list.get(0);
>>
>> I believe, it was discussed in context of pattern matching.
>>
>> With best regards,
>> Tagir Valeev.
>>
>> On Fri, Oct 6, 2017 at 6:16 PM, Remi Forax <forax at univ-mlv.fr> wrote:
>>> Hi all,
>>> The JEP 302 list some improvements but I think some are missing,
>>> obviously, it's up to debate :)
>>>
>>> So here is my list of left leftovers:
>>> - support throw statement as a lambda expression
>>>
>>> I think we have already discussed informally about this one.
>>> The compiler should allow to have a lambda expression that starts
>>> with throw.
>>>
>>> so a code like this will become valid
>>> merge(key, value, (_, _) -> throw new IllegalStateException("key
>>> " + key + " already present));
>>>
>>>
>>> - allow void to be converted to Void (by returning null)
>>>
>>> This proposal is perhaps more controversial, currently there is
>>> no way to simply convert a lambda statement to a lambda expression.
>>> So a code like will compile
>>>
>>> <T, R> R sync(T initial, Function<? super T, ? extends R> fun) {
>>> synchronized(lock) {
>>> return fun.apply(initial);
>>> }
>>> }
>>>
>>> Consumer<String> c = System.out::println;
>>> sync("foo", c::accept); // the compiler should generate a
>>> synthetic static method that returns null
>>>
>>> This proposal is problematic because:
>>> - it implicitly produces a null, which is a bad idea
>>> - if there are several overloads, a lambda statement can now
>>> match more methods so the compiler may reject code that was
>>> previously working or worst call another method that the one that
>>> was originally selected.
>>>
>>>
>>> The other question is should the conversion be extended to work
>>> with non lambda code,
>>> i.e. consider that 'return' or an implcit 'return' can be
>>> trasformed to a return null by the compiler.
>>>
>>> Void m() {
>>> return; // the compiler generates return null;
>>> }
>>>
>>> Void m() { } // the compiler generates return null;
>>>
>>>
>>> On the positive side, it mix well with the switch expression
>>> proposed in the Pattern Matching JEP.
>>>
>>> Supplier<Void> supplier =
>>> () -> switchexpr(someValue) {
>>> case 0 -> System.out.println("foo");
>>> default -> { /* empty */ }
>>> };
>>>
>>>
>>> regards,
>>> Rémi
>>>
>>> [1] http://openjdk.java.net/jeps/302
>
More information about the amber-spec-experts
mailing list