<html><head><meta http-equiv="Content-Type" content="text/html charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class="">On Mar 18, 2017, at 3:32 PM, <a href="mailto:forax@univ-mlv.fr" class="">forax@univ-mlv.fr</a> wrote:<br class=""><div><blockquote type="cite" class=""><br class="Apple-interchange-newline"><div class=""><span style="font-family: Helvetica; font-size: 16px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">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.</span><br style="font-family: Helvetica; font-size: 16px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""></div></blockquote></div><br class=""><div class="">Good point. Some form of post-facto interface injection (if we could figure</div><div class="">out the details, which is very hard) would presumably address this problem.</div><div class=""><br class=""></div><div class="">The issue of visitors and matchers is important because if we introduce</div><div class="">a new kind of class (data class, record class, whatever) with enhanced</div><div class="">pattern capabilities, we have basically one chance to define a universal</div><div class="">pattern match interface for that kind of class. (We could add it in after</div><div class="">first release, but it's hard to add more than once.)</div><div class=""><br class=""></div><div class="">Here's a second point of similar weight: The interface itself has parts</div><div class="">which are signature-polymorphic. If you try to represent it as a classic</div><div class="">Java interface you can see that the polymorphism causes boxing:</div><div class=""><br class=""></div><div class="">interface Matchable<R extends Matchable.Result> {</div><div class=""> R match();</div><div class="">}</div><div class=""><br class=""></div><div class="">Whatever the API structure is for match patterns and results,</div><div class="">the result eventually has to deliver a tuple of extracted values.</div><div class="">But there is no good way (yet, until value types and any-generics)</div><div class="">to express the type of a tuple. So we get List<Object>, etc.</div><div class=""><br class=""></div><div class="">The closest we can get to a tuple type in the JVM is an argument</div><div class="">list type, reified as a MethodType and accepted by a MethodHandle.</div><div class="">Therefore, I think a workable "Matchable" API can involve method</div><div class="">handles and be type-classified by MethodTypes (returning a</div><div class="">conventional void result).</div><div class=""><br class=""></div><div class="">As a first cut:</div><div class=""><br class=""></div><div class="">interface Matchable<MT extends MethodType<void, A...>> {</div><div class=""> boolean match(MethodHandle<MT> collector);</div><div class=""> MT matchType();</div><div class="">}</div><div class=""><br class=""></div><div class="">(The pattern part of the match is left out for clarity.</div><div class="">You can put it back in easily enough as another argument</div><div class="">to the "match" call. Maybe match is overloaded by pattern</div><div class="">kind.)</div><div class=""><br class=""></div><div class="">The type variable decorations are ill-defined and have to</div><div class="">be stripped out of the real code.</div><div class=""><br class=""></div><div class="">Second cut:</div><div class=""><br class=""></div><div class=""><div class="">interface Matchable<MT extends MethodType<void, A…>> {</div><div class=""> BUF match(); // returns null on failure, buffered match-values on success</div><div class=""> <R> R matchExtract(BUF, MethodHandle<MethodType<R, A…>> collector);</div><div class=""> MT matchType();</div><div class="">}</div></div><div class=""><br class=""></div><div class="">The extract calls either look into the match-result buffer</div><div class="">for the required match components, or (as an optimization)</div><div class="">might look directly into the object fields, if it is safe to do so.</div><div class=""><br class=""></div><div class="">A third cut might break the mold completely (of a classic</div><div class="">interface) and present the Matchable API as a statically</div><div class="">linkable bundle of method handles, one bundle per match</div><div class="">API binding (i.e., per concrete class). The bundle would</div><div class="">look like:</div><div class=""><br class=""></div><div class="">interface Extractor<T, BUF, MT extends MethodType<void, A…>> {</div><div class=""> MethodHandle<BUF, T> matchHandle(); // null on failure, T or other value on success</div><div class=""> MethodHandle<?, T, BUF> componentHandle(int i); // extract one of the A values</div><div class=""><div class=""> MT matchType();</div><div class=""> Class<T> targetType();</div><div class=""> Class<BUF> bufferType();</div><div class="">}</div></div><div class=""><br class=""></div><div class="">You could omit the BUF type completely, but there is a big cost:</div><div class="">There is no way for the T object to deliver a tuple of types apart from</div><div class="">being willing at any moment to be the subject of an accessor call.</div><div class="">Those accessor calls will need in general to do redundant calculations</div><div class="">and are subject to race conditions which might make the match</div><div class="">disappear before the components were extracted.</div><div class=""><br class=""></div><div class="">The presence of the T type (alongside BUF) in the component</div><div class="">handles allows an object with immutable fields to deliver those</div><div class="">particular values by direct access, instead of copying them</div><div class="">through a buffer object.</div><div class=""><br class=""></div><div class="">The BUF type is secret to the implementation of T. You can</div><div class="">use an extractor without knowing it except via a wildcard.</div><div class=""><br class=""></div><div class="">— John</div></body></html>