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