<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
</head>
<body>
<p>On 05. 08. 22 22:52, <a class="moz-txt-link-abbreviated" href="mailto:forax@univ-mlv.fr">forax@univ-mlv.fr</a> wrote:<br>
</p>
<blockquote type="cite" cite="mid:1724934379.19079517.1659732755546.JavaMail.zimbra@u-pem.fr">
<pre class="moz-quote-pre" wrap="">[...]
</pre>
<blockquote type="cite">
<blockquote type="cite">
<blockquote type="cite">
<pre class="moz-quote-pre" wrap="">In any case, I'm a bit afraid that we could enhance a translation patch
forever, always adding new cases that can be optimized. So, I think we
need to draw a line somewhere where the patch provides a benefit while
still being testable and reviewable. With a possible separate
improvements, if they prove to be useful. It is possible I haven't drawn
the line far enough, but looking at the patch, it seems complex enough.
</pre>
</blockquote>
<pre class="moz-quote-pre" wrap="">I think the issue is that a list of pattern is not the right intermediary
structure to try to optimize the pattern matching, a decision tree is a better
intermediary representation (this is how pattern matching is usually optimized,
i've not invented something new :) )
Here is an example of such decision tree:
<a class="moz-txt-link-freetext" href="https://urldefense.com/v3/__https://github.com/forax/switch-pattern-combinator__;!!ACWV5N9M2RV99hQ!JevAQE8IkRf4n-BMKA2sMTNFfJ5sAyJ1xopR2O9rq_45-xqaHOgirecR8E4zIGB_RgMb27G3tlcHEuGADjk$">https://urldefense.com/v3/__https://github.com/forax/switch-pattern-combinator__;!!ACWV5N9M2RV99hQ!JevAQE8IkRf4n-BMKA2sMTNFfJ5sAyJ1xopR2O9rq_45-xqaHOgirecR8E4zIGB_RgMb27G3tlcHEuGADjk$</a>
</pre>
</blockquote>
<pre class="moz-quote-pre" wrap="">
I am not really opposed to having an intermediate structure, but I think
the overall cost of the structure is likely to be significant, and it
should provide significantly better code to offset that.
</pre>
</blockquote>
<pre class="moz-quote-pre" wrap="">
I agree.
</pre>
<blockquote type="cite">
<pre class="moz-quote-pre" wrap="">
Looking at the page, I see:
The advantage of a decision tree is that if two patterns have a common
prefix, the code for the common prefix is generated only once.
I wonder if there's a *conceptual* difference between what this PR is
doing and what your code is doing. The PR here is trying to take common
prefixes (of viable cases) and generate code for them only once. I don't
think that not optimizing
case A(String s) -> {}
case A a -> {}
is a conceptual difference, but if this is something that is seen as
critical, I am fairly sure I can implement that without creating a brand
new structure and code to convert the AST into it and back.
</pre>
</blockquote>
<pre class="moz-quote-pre" wrap="">
You need the intermediary structure when the common prefix are not subsequent
case A(B b) ->
case B(A a) ->
case A(C c) ->
Here the first and the last case shares a common prefix. </pre>
</blockquote>
<p><br>
</p>
<p>Sorry, but I don't see why I can't do this particular thing
without a specialized intermediate representation. A bigger
question, I think, is when it is safe to do so, and when not.</p>
<p><br>
</p>
<blockquote type="cite" cite="mid:1724934379.19079517.1659732755546.JavaMail.zimbra@u-pem.fr">
<pre class="moz-quote-pre" wrap="">
</pre>
<blockquote type="cite">
<pre class="moz-quote-pre" wrap="">
It is also true the current code does not reorder the cases. I am not
sure if your code does reordering, but I didn't see a set of rules for
safe reorderings, which I think is the biggest problem here. My thinking
of safe rules for reordering was limited so far, and the ability to
reorder cases may be limited due to guards and separate compilation
considerations (we can also have new pattern types which may limit our
ability to reorder cases). But even though this PR does not reorder
cases, it is in principle doable.
</pre>
</blockquote>
<pre class="moz-quote-pre" wrap="">
One of the reason to backpedal on the idea of guarded patterns is to try to cleanly separate what can do side effects thus limit the reordering and what should not do side effects.
A guard can do side effect thus it's not a pattern. A deconstructing pattern using a deconstructor should not do side effect ("should not" like in a stream, if you do it, you are on your own) because it's a pattern.
</pre>
<blockquote type="cite">
<pre class="moz-quote-pre" wrap="">
Situation would, of course, be different if we tried to optimize not
only prefixes of the patterns - but this does not seem to be the
proposal in switch-pattern-combinator.
As for casting to the last permitted type - I don't see how this relates
to decision trees. While casting and catching might look interesting
from the bytecode perspective, it is something that is likely to be
relatively complex to implement in javac, and using an (effective)
instanceof and an explicit fallback does not really sound terrible.
</pre>
</blockquote>
<pre class="moz-quote-pre" wrap="">
The idea of using a cast is that you provide a good error message to the users because the ClassCastException stores the class that is not handled by the pattern matching.
You loose that information if you use an explicit fallback.</pre>
</blockquote>
<p><br>
</p>
<p>Sorry, but if I understand what you are proposing is:</p>
<p>B b = (B) obj; //magical catch handler somewhere handling the CCE</p>
<p>$rest$;<br>
</p>
<p><br>
</p>
<p>what I am saying is that this can be achieved by an analog of:</p>
<p>if (obj instanceof B b) {</p>
<p> $rest$;</p>
<p>} else {</p>
<p> throw <an-exception-we-want>(obj.getClass());</p>
<p>}</p>
<p><br>
</p>
<p>What information is lost?<br>
</p>
<p><br>
</p>
<blockquote type="cite" cite="mid:1724934379.19079517.1659732755546.JavaMail.zimbra@u-pem.fr">
<pre class="moz-quote-pre" wrap="">
</pre>
<blockquote type="cite">
<pre class="moz-quote-pre" wrap="">There is also a question on when this is safe to do - if there's a `case
Object o` at the end of the switch, then probably this is not correct to
do anyway, etc.
</pre>
</blockquote>
<pre class="moz-quote-pre" wrap="">
It is safe to do if the compiler has type-checked the patterns before, the cast is only done in case of a sealed type, not if there is a common supertype at the end.</pre>
</blockquote>
<p><br>
</p>
<p>I mean - consider:</p>
<p>sealed interface I {}</p>
<p>final class OnlySubtypeAtCompileTime implements I {}</p>
<p>record Box(I i) {}</p>
<p><br>
</p>
<p>Object b = new
Box(<a-new-subtype-not-known-at-compile-time>);</p>
<p>switch (b) {</p>
<p> case Box(OnlySubtypeAtCompileTime t) ->
System.err.println("Should probably not fail here,");<br>
</p>
<p> case Object obj -> System.err.println("but should end up
here.");</p>
<p>}</p>
<p><br>
</p>
<blockquote type="cite" cite="mid:1724934379.19079517.1659732755546.JavaMail.zimbra@u-pem.fr">
<pre class="moz-quote-pre" wrap="">
</pre>
<blockquote type="cite">
<pre class="moz-quote-pre" wrap="">
Regarding deferring all this to runtime, that has definitely a lot of
desirable properties. And there were multiple experiments with that.
But, the API for that is fairly complex - probably easier to do now when
we have guards on cases, not guarded patterns, but still likely
significant. (Overall, guard are really tough, because they a) capture;
b) provide new bindings.)
</pre>
</blockquote>
<pre class="moz-quote-pre" wrap="">
"provide new bindings" => do you have an example of that ?</pre>
</blockquote>
<p><br>
</p>
<p>Sure:</p>
<p><span style="font-family:monospace"><span style="color:#000000;background-color:#ffffff;">public class
TA {
</span><br>
public static void main(String... args) {
<br>
Object o = new Box("");
<br>
switch (o) {
<br>
case Box b when b.o() instanceof String s ->
System.err.println(s);
<br>
default -> {}
<br>
}
<br>
}
<br>
record Box(Object o) {}
<br>
}<br>
<br>
<br>
</span></p>
<p>(There can be any number of new bindings from the guard, of
course.)</p>
<p><br>
</p>
<blockquote type="cite" cite="mid:1724934379.19079517.1659732755546.JavaMail.zimbra@u-pem.fr">
<pre class="moz-quote-pre" wrap="">
I don't think a guard should be allowed to do that. It looks like a big gunfoot to me.</pre>
</blockquote>
<p><br>
</p>
<p>I believe the current specification supports guards that
introduce new bindings:</p>
<p><a class="moz-txt-link-freetext" href="http://cr.openjdk.java.net/~gbierman/jep427%2b405/jep427+405-20220601/specs/patterns-switch-record-patterns-jls.html#jls-6.3.4">http://cr.openjdk.java.net/~gbierman/jep427%2b405/jep427+405-20220601/specs/patterns-switch-record-patterns-jls.html#jls-6.3.4</a></p>
<p><br>
</p>
<p>To me, it seems desirable. In any case, an implementation PR is
probably not very well suited to discuss opinions on what should
be specced. In particular (but not only) a PR that is not expected
to change the semantics.<br>
</p>
<p><br>
</p>
<p>Jan</p>
<p><br>
</p>
<blockquote type="cite" cite="mid:1724934379.19079517.1659732755546.JavaMail.zimbra@u-pem.fr">
<pre class="moz-quote-pre" wrap="">
</pre>
<blockquote type="cite">
<pre class="moz-quote-pre" wrap="">
Thanks,
Jan
</pre>
</blockquote>
<pre class="moz-quote-pre" wrap="">
regards,
Rémi
</pre>
</blockquote>
</body>
</html>