Pattern matching for java.util.Optional

Brian Goetz brian.goetz at oracle.com
Fri Jan 26 11:42:38 UTC 2024


Let's step back, because your question is caught up in the details of a 
solution, rather than focusing on the problem.

Obviously we want to be able to pattern match on Optional.  You've gone 
down the road of "We have pattern matching for ADTs, so let's turn 
Optional into an ADT, and then pattern match on that", and then got 
caught in the details of whether this is a compatible refactoring.

But I don't think we have to, or should, refactor the representation to 
"match" the pattern machinery.  As outlined in "Towards Member Patterns" 
and "Patterns in the Object Model", we want to use the same tools for 
destructuring as we do for aggregation.  Optional is assembled with 
static factories; we should be able to take it apart with static patterns:

     switch (o) {
         case Optional.of(var e): ...
         case Optional.empty(): ...
     }

Adding `Some` and `None` deconstruction patterns would work, but then we 
lose the correspondence between "how we put it together" and "how we 
take it apart."  So I don't want to go down this road.  (Another reason 
to not go down this road is that we want Optional to work as a value 
type, which means one implementation.)

There are a few details yet to be wrapped up (e.g., how do we denote the 
of/empty pair as exhaustive).

On 1/26/2024 2:30 AM, Red IO wrote:
> Now that pattern matching is nearly complete I was thinking about the 
> distinction how the option type of the jdk works.
> What I'm talking about is the split between checking if it's empty and 
> retrieving the value.
> Sure there are ways to transform the optional and GetOrElse and Throw 
> varients. But none of them express the connection between isPresent 
> and get:
> var option = Optional.of("Foo");
> if (option.isPresent()) {
> var foo = option.get();
> }
> Now pattern matching comes into play. A great solution that is used by 
> many other languages to deal with the option type is matching rather 
> or not it's present and in the same step providing the value to the 
> valid code block. Something like this:
> var option = Optional.of("Foo");
> switch(option) {
> case Some(foo) -> {}
> case None() -> {}
> }
> Or
> if(option instanceof Some(foo) {
>
> }
>
> This is indeed possible in the current version of java using sealed 
> types, records and pattern matching.
> Now it's sad that Optional was introduced before the features we have 
> now where available and introducing a second option type would be 
> confusing and terrible for apis.
>
> But I don't think all hope is lost yet. I'm not too familiar with 
> binary compatibility but from an api standpoint it would not change 
> the public api of optional if it was turned from a final class into a 
> sealed interface with 2 inner records representing the 2 states of the 
> Optional instead of a nullable field. This way the public api of 
> optional would just be added 2 inner types and otherwise stay the same.
>
> I would love to hear your feedback on this one.
>
> Great regards
> RedIODev
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/amber-dev/attachments/20240126/3c6923bd/attachment-0001.htm>


More information about the amber-dev mailing list