[patterns] Destructuring without matching?

Tagir Valeev amaembo at gmail.com
Sun Jul 9 02:22:26 UTC 2017


Hello, Remi,  Brian!

Yes, I was thinking about separate operator / syntax construct like 'let'
in Remi example. I don't propose changing 'matching' behavior: when type is
specified, it should be consistent with 'instanceof' which doesn't match
null.

With best regards,
Tagir Valeev.

8 июля 2017 г. 2:59 AM пользователь "Remi Forax" <forax at univ-mlv.fr>
написал:

> Hi Tagir,
>
> ----- Mail original -----
> > De: "Tagir Valeev" <amaembo at gmail.com>
> > À: amber-dev at openjdk.java.net
> > Envoyé: Vendredi 7 Juillet 2017 17:21:28
> > Objet: [patterns] Destructuring without matching?
>
> > Hello!
> >
> > Sometimes it's reasonable to deconstruct the object of known type. A
> > classical example is Map.Entry. E.g. currently I can write:
> >
> > // Map<String, Integer> wordCounts
> > wordCounts.entrySet().stream()
> >  .filter(e -> e.getValue() > 10)
> >  .map(e -> e.getKey()+": "+e.getValue())
> >  .forEach(System.out::println);
> >
> > It's desired to refer by concrete name to key and value like this:
> >
> > wordCounts.entrySet().stream()
> >  .filter((_, count) -> count > 10)
> >  .map((word, count) -> word+": "+count)
> >  .forEach(System.out::println);
> >
> > Of course such syntax is not possible. Reading pattern matching proposal
> I
> > thought whether it could solve this somehow. I see these alternatives:
> >
> > wordCounts.entrySet().stream()
> >  .filter(e -> e matches Entry(_, count) && count > 10)
> >  .map(e -> e matches Entry(word, count) ? word+": "+count : null)
> >  .forEach(System.out::println);
> >
> > Or
> >
> > wordCounts.entrySet().stream()
> >  .filter(e -> exprswitch(e) {case Entry(_, count) -> count > 10; default
> > -> false;})
> >  .map(e -> exprswitch(e) {case Entry(word, count) -> word+": "+count;
> > default -> null;})
> >  .forEach(System.out::println);
> >
> > In the latter case default branch is redundant as we know that e is
> always
> > an Entry. Probably compiler could figure out this as well and do not
> > require default branch? In this case exprswitch will have only one branch
> > and looks too verbose.
>
> yes, the compiler can figure that you do not need a default branch.
>
> But for what you want you do not need to match/switch on things, you just
> want destructuration.
>
> I think it's better to have a new operator, let call it 'let' that does
> the same destructuration that the pattern matching does,
>
> wordCounts.entrySet().stream()
>   .filter(e -> let (_, count) = e; count > 10)
>   .map(e -> let(word, count) = e; word+": "+count)
>   .forEach(System.out::println);
>
> and given that we already have a way to support string interpolation in
> the JDK (StringConcatFactory),
> you can even add String interpolation in the mix,
>
> wordCounts.entrySet().stream()
>   .filter(e -> let (_, count) = e; count > 10)
>   .map(e -> let (word, count) = e; ''$(word): $(count)'')
>   .forEach(System.out::println);
>
> (you need a way to said that a String is interpolated, i've chosen ''
> (quotequote) which is close to " and currently invalid)
>
> and with values types (thus tuples), you can write it that way,
>
> wordCounts.entrySet().stream()
>   .map(e -> let (word, count) = e; (word, count))
>   .filter((_, count) -> count > 10)
>   .map((word, count) -> ''$(word): $(count)'')
>   .forEach(System.out::println);
>
> regards,
> Rémi
>
> > Tagir Valeev.
>


More information about the amber-dev mailing list