[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