Pattern Matching
Andrey Breslav
andrey.breslav at jetbrains.com
Tue Mar 28 08:04:57 UTC 2017
For completeness, since Remi aimed at listing all alternatives, I think we
should not forget Object algebras:
https://www.cs.utexas.edu/~wcook/Drafts/2012/ecoop2012.pdf
My experience has been that this pattern is good for observing data
structures (transforming, pretty-printing, etc), but it's usually hard to
implement, say, equals() through it.
On Tue, Mar 28, 2017 at 12:40 AM John Rose <john.r.rose at oracle.com> wrote:
> On Mar 18, 2017, at 3:32 PM, forax at univ-mlv.fr wrote:
>
>
> The main issue of the visitor is that you have to add the accept methods
> on the class of the hierarchy before being able to use the visitor, this is
> equivalent to be able to insert a method or a constant into a class, which
> is also equivalent to be able to inject the implementation of a not yet
> existing interface.
>
>
> Good point. Some form of post-facto interface injection (if we could
> figure
> out the details, which is very hard) would presumably address this problem.
>
> The issue of visitors and matchers is important because if we introduce
> a new kind of class (data class, record class, whatever) with enhanced
> pattern capabilities, we have basically one chance to define a universal
> pattern match interface for that kind of class. (We could add it in after
> first release, but it's hard to add more than once.)
>
> Here's a second point of similar weight: The interface itself has parts
> which are signature-polymorphic. If you try to represent it as a classic
> Java interface you can see that the polymorphism causes boxing:
>
> interface Matchable<R extends Matchable.Result> {
> R match();
> }
>
> Whatever the API structure is for match patterns and results,
> the result eventually has to deliver a tuple of extracted values.
> But there is no good way (yet, until value types and any-generics)
> to express the type of a tuple. So we get List<Object>, etc.
>
> The closest we can get to a tuple type in the JVM is an argument
> list type, reified as a MethodType and accepted by a MethodHandle.
> Therefore, I think a workable "Matchable" API can involve method
> handles and be type-classified by MethodTypes (returning a
> conventional void result).
>
> As a first cut:
>
> interface Matchable<MT extends MethodType<void, A...>> {
> boolean match(MethodHandle<MT> collector);
> MT matchType();
> }
>
> (The pattern part of the match is left out for clarity.
> You can put it back in easily enough as another argument
> to the "match" call. Maybe match is overloaded by pattern
> kind.)
>
> The type variable decorations are ill-defined and have to
> be stripped out of the real code.
>
> Second cut:
>
> interface Matchable<MT extends MethodType<void, A…>> {
> BUF match(); // returns null on failure, buffered match-values on
> success
> <R> R matchExtract(BUF, MethodHandle<MethodType<R, A…>> collector);
> MT matchType();
> }
>
> The extract calls either look into the match-result buffer
> for the required match components, or (as an optimization)
> might look directly into the object fields, if it is safe to do so.
>
> A third cut might break the mold completely (of a classic
> interface) and present the Matchable API as a statically
> linkable bundle of method handles, one bundle per match
> API binding (i.e., per concrete class). The bundle would
> look like:
>
> interface Extractor<T, BUF, MT extends MethodType<void, A…>> {
> MethodHandle<BUF, T> matchHandle(); // null on failure, T or other
> value on success
> MethodHandle<?, T, BUF> componentHandle(int i); // extract one of the A
> values
> MT matchType();
> Class<T> targetType();
> Class<BUF> bufferType();
> }
>
> You could omit the BUF type completely, but there is a big cost:
> There is no way for the T object to deliver a tuple of types apart from
> being willing at any moment to be the subject of an accessor call.
> Those accessor calls will need in general to do redundant calculations
> and are subject to race conditions which might make the match
> disappear before the components were extracted.
>
> The presence of the T type (alongside BUF) in the component
> handles allows an object with immutable fields to deliver those
> particular values by direct access, instead of copying them
> through a buffer object.
>
> The BUF type is secret to the implementation of T. You can
> use an extractor without knowing it except via a wildcard.
>
> — John
>
--
Andrey Breslav
Project Lead of Kotlin
JetBrains
http://kotlinlang.org/
The Drive to Develop
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.openjdk.java.net/pipermail/amber-spec-experts/attachments/20170328/dbdcf402/attachment-0001.html>
More information about the amber-spec-experts
mailing list