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