<html><body><div style="font-family: arial, helvetica, sans-serif; font-size: 12pt; color: #000000"><div><br></div><div><br></div><hr id="zwchr" data-marker="__DIVIDER__"><div data-marker="__HEADERS__"><blockquote style="border-left:2px solid #1010FF;margin-left:5px;padding-left:5px;color:#000;font-weight:normal;font-style:normal;text-decoration:none;font-family:Helvetica,Arial,sans-serif;font-size:12pt;"><b>From: </b>"Viktor Klang" <viktor.klang@oracle.com><br><b>To: </b>"Remi Forax" <forax@univ-mlv.fr>, "core-libs-dev" <core-libs-dev@openjdk.java.net><br><b>Sent: </b>Wednesday, January 17, 2024 5:49:01 PM<br><b>Subject: </b>Re: Gatherer API : wildcards complaint<br></blockquote></div><div><style style="display:none;"> P {margin-top:0;margin-bottom:0;} </style></div><div data-marker="__QUOTED_TEXT__"><blockquote style="border-left: 2px solid #1010FF; margin-left: 5px; padding-left: 5px; color: #000; font-weight: normal; font-style: normal; text-decoration: none; font-family: Helvetica,Arial,sans-serif; font-size: 12pt;" data-mce-style="border-left: 2px solid #1010FF; margin-left: 5px; padding-left: 5px; color: #000; font-weight: normal; font-style: normal; text-decoration: none; font-family: Helvetica,Arial,sans-serif; font-size: 12pt;"><div><span style="font-family: Aptos, Aptos_EmbeddedFont, Aptos_MSFontService, Calibri, Helvetica, sans-serif; font-size: 12pt; color: #000000;" data-mce-style="font-family: Aptos, Aptos_EmbeddedFont, Aptos_MSFontService, Calibri, Helvetica, sans-serif; font-size: 12pt; color: #000000;">Hi Rémi,</span></div><div class="elementToProof"><span style="font-family: Aptos, Aptos_EmbeddedFont, Aptos_MSFontService, Calibri, Helvetica, sans-serif; font-size: 12pt; color: #000000;" data-mce-style="font-family: Aptos, Aptos_EmbeddedFont, Aptos_MSFontService, Calibri, Helvetica, sans-serif; font-size: 12pt; color: #000000;"><br></span></div><div class="elementToProof"><span style="font-family: Aptos, Aptos_EmbeddedFont, Aptos_MSFontService, Calibri, Helvetica, sans-serif; font-size: 12pt; color: #000000;" data-mce-style="font-family: Aptos, Aptos_EmbeddedFont, Aptos_MSFontService, Calibri, Helvetica, sans-serif; font-size: 12pt; color: #000000;">Thank you for the feedback—examples would be </span><span style="font-family: Aptos, Aptos_EmbeddedFont, Aptos_MSFontService, Calibri, Helvetica, sans-serif; font-size: 12pt; color: #000000;" data-mce-style="font-family: Aptos, Aptos_EmbeddedFont, Aptos_MSFontService, Calibri, Helvetica, sans-serif; font-size: 12pt; color: #000000;">much appreciated!</span></div></blockquote><div><br></div><div>Here is an example with an interface and a class,</div><div><br></div><div><div style="background-color: #ffffff; color: #080808;" data-mce-style="background-color: #ffffff; color: #080808;"><pre style="font-family: 'JetBrains Mono',monospace; font-size: 9.8pt;" data-mce-style="font-family: 'JetBrains Mono',monospace; font-size: 9.8pt;"><span style="color: #0033b3;" data-mce-style="color: #0033b3;">interface </span><span style="color: #000000;" data-mce-style="color: #000000;">Counter </span>{<br>  <span style="color: #0033b3;" data-mce-style="color: #0033b3;">void </span><span style="color: #00627a;" data-mce-style="color: #00627a;">increment</span>();<br>  <span style="color: #0033b3;" data-mce-style="color: #0033b3;">int </span><span style="color: #00627a;" data-mce-style="color: #00627a;">value</span>();<br>}<br><br><span style="color: #000000;" data-mce-style="color: #000000;">Gatherer</span><<span style="color: #000000;" data-mce-style="color: #000000;">String</span>, <span style="color: #000000;" data-mce-style="color: #000000;">Counter</span>, <span style="color: #000000;" data-mce-style="color: #000000;">Integer</span>> <span style="color: #00627a;" data-mce-style="color: #00627a;">count</span>() {<br>  <span style="color: #0033b3;" data-mce-style="color: #0033b3;">class </span><span style="color: #000000;" data-mce-style="color: #000000;">CounterImpl </span><span style="color: #0033b3;" data-mce-style="color: #0033b3;">implements </span><span style="color: #000000;" data-mce-style="color: #000000;">Counter </span>{<br>    <span style="color: #0033b3;" data-mce-style="color: #0033b3;">int </span><span style="color: #871094;" data-mce-style="color: #871094;">counter</span>;<br><br>    <span style="color: #9e880d;" data-mce-style="color: #9e880d;">@Override<br></span><span style="color: #9e880d;" data-mce-style="color: #9e880d;">    </span><span style="color: #0033b3;" data-mce-style="color: #0033b3;">public void </span><span style="color: #00627a;" data-mce-style="color: #00627a;">increment</span>() {<br>      <span style="color: #871094;" data-mce-style="color: #871094;">counter</span>++;<br>    }<br><br>    <span style="color: #9e880d;" data-mce-style="color: #9e880d;">@Override<br></span><span style="color: #9e880d;" data-mce-style="color: #9e880d;">    </span><span style="color: #0033b3;" data-mce-style="color: #0033b3;">public int </span><span style="color: #00627a;" data-mce-style="color: #00627a;">value</span>() {<br>      <span style="color: #0033b3;" data-mce-style="color: #0033b3;">return </span><span style="color: #871094;" data-mce-style="color: #871094;">counter</span>;<br>    }<br>  }<br>  <span style="color: #000000;" data-mce-style="color: #000000;">Supplier</span><<span style="color: #000000;" data-mce-style="color: #000000;">CounterImpl</span>> <span style="color: #000000;" data-mce-style="color: #000000;">initializer </span>= <span style="color: #000000;" data-mce-style="color: #000000;">CounterImpl</span>::<span style="color: #0033b3;" data-mce-style="color: #0033b3;">new</span>;<br>  <span style="color: #000000;" data-mce-style="color: #000000;">Gatherer</span>.<span style="color: #000000;" data-mce-style="color: #000000;">Integrator</span><<span style="color: #000000;" data-mce-style="color: #000000;">Counter</span>, <span style="color: #000000;" data-mce-style="color: #000000;">String</span>, <span style="color: #000000;" data-mce-style="color: #000000;">Gatherer</span>.<span style="color: #000000;" data-mce-style="color: #000000;">Downstream</span><? <span style="color: #0033b3;" data-mce-style="color: #0033b3;">super </span><span style="color: #000000;" data-mce-style="color: #000000;">Integer</span>>> <span style="color: #000000;" data-mce-style="color: #000000;">integrator </span>= (<span style="color: #000000;" data-mce-style="color: #000000;">counter</span>, <span style="color: #000000;" data-mce-style="color: #000000;">_</span>, <span style="color: #000000;" data-mce-style="color: #000000;">_</span>) -> {<br>    <span style="color: #000000;" data-mce-style="color: #000000;">counter</span>.increment();<br>    <span style="color: #0033b3;" data-mce-style="color: #0033b3;">return true</span>;<br>  };<br>  <span style="color: #000000;" data-mce-style="color: #000000;">BiConsumer</span><<span style="color: #000000;" data-mce-style="color: #000000;">Counter</span>, <span style="color: #000000;" data-mce-style="color: #000000;">Gatherer</span>.<span style="color: #000000;" data-mce-style="color: #000000;">Downstream</span><? <span style="color: #0033b3;" data-mce-style="color: #0033b3;">super </span><span style="color: #000000;" data-mce-style="color: #000000;">Integer</span>>> <span style="color: #000000;" data-mce-style="color: #000000;">finisher </span>= (<span style="color: #000000;" data-mce-style="color: #000000;">counter</span>, <span style="color: #000000;" data-mce-style="color: #000000;">downstream</span>) -> {<br>    <span style="color: #000000;" data-mce-style="color: #000000;">downstream</span>.push(<span style="color: #000000;" data-mce-style="color: #000000;">counter</span>.value());<br>  };<br>  <span style="color: #8c8c8c; font-style: italic;" data-mce-style="color: #8c8c8c; font-style: italic;"></span><span style="color: #0033b3;" data-mce-style="color: #0033b3;">return </span><span style="color: #000000;" data-mce-style="color: #000000;">Gatherer</span>.<span style="font-style: italic;" data-mce-style="font-style: italic;">ofSequential</span>(<span style="color: #000000;" data-mce-style="color: #000000;">initializer</span>, <span style="color: #000000;" data-mce-style="color: #000000;">integrator</span>, <span style="color: #000000;" data-mce-style="color: #000000;">finisher</span>);    <span style="color: #8c8c8c; font-style: italic;" data-mce-style="color: #8c8c8c; font-style: italic;">// does not compile :(</span><span style="color: #8c8c8c; font-style: italic;" data-mce-style="color: #8c8c8c; font-style: italic;"></span><br>}<br><br><span style="color: #0033b3;" data-mce-style="color: #0033b3;">void </span><span style="color: #00627a;" data-mce-style="color: #00627a;">main</span>() {<br><span style="color: #000000;" data-mce-style="color: #000000;">  System</span>.<span style="color: #871094; font-style: italic;" data-mce-style="color: #871094; font-style: italic;">out</span>.println(<span style="color: #000000;" data-mce-style="color: #000000;">Stream</span>.<span style="font-style: italic;" data-mce-style="font-style: italic;">of</span>(<span style="color: #067d17;" data-mce-style="color: #067d17;">"foo"</span>).gather(count()).findFirst().orElseThrow());<br>}</pre></div></div><div><br></div><div>if instead of explicitly typing each functions, we directly call ofSequential, it works</div><div><br></div><div><div style="background-color: #ffffff; color: #080808;" data-mce-style="background-color: #ffffff; color: #080808;"><pre style="font-family: 'JetBrains Mono',monospace; font-size: 9.8pt;" data-mce-style="font-family: 'JetBrains Mono',monospace; font-size: 9.8pt;"><span style="color: #0033b3;" data-mce-style="color: #0033b3;">return </span><span style="color: #000000;" data-mce-style="color: #000000;">Gatherer</span>.<span style="font-style: italic;" data-mce-style="font-style: italic;">ofSequential</span>(<br>    <span style="color: #000000;" data-mce-style="color: #000000;">CounterImpl</span>::<span style="color: #0033b3;" data-mce-style="color: #0033b3;">new</span>,<br>    (<span style="color: #000000;" data-mce-style="color: #000000;">Counter counter</span>, <span style="color: #000000;" data-mce-style="color: #000000;">String _</span>, <span style="color: #000000;" data-mce-style="color: #000000;">Gatherer</span>.<span style="color: #000000;" data-mce-style="color: #000000;">Downstream</span><? <span style="color: #0033b3;" data-mce-style="color: #0033b3;">super </span><span style="color: #000000;" data-mce-style="color: #000000;">Integer</span>> <span style="color: #000000;" data-mce-style="color: #000000;">_</span>) -> {<br>      <span style="color: #000000;" data-mce-style="color: #000000;">counter</span>.increment();<br>      <span style="color: #0033b3;" data-mce-style="color: #0033b3;">return true</span>;<br>    },<br>    (<span style="color: #000000;" data-mce-style="color: #000000;">Counter counter</span>, <span style="color: #000000;" data-mce-style="color: #000000;">Gatherer</span>.<span style="color: #000000;" data-mce-style="color: #000000;">Downstream</span><? <span style="color: #0033b3;" data-mce-style="color: #0033b3;">super </span><span style="color: #000000;" data-mce-style="color: #000000;">Integer</span>> <span style="color: #000000;" data-mce-style="color: #000000;">downstream</span>) -> {<br>      <span style="color: #000000;" data-mce-style="color: #000000;">downstream</span>.push(<span style="color: #000000;" data-mce-style="color: #000000;">counter</span>.value());<br>    }<br>);</pre></div></div><div><br data-mce-bogus="1"></div><div>because here, CounterImpl::new is inferred as Supplier<Counter>.<br data-mce-bogus="1"></div><div><br data-mce-bogus="1"></div><blockquote style="border-left: 2px solid #1010FF; margin-left: 5px; padding-left: 5px; color: #000; font-weight: normal; font-style: normal; text-decoration: none; font-family: Helvetica,Arial,sans-serif; font-size: 12pt;" data-mce-style="border-left: 2px solid #1010FF; margin-left: 5px; padding-left: 5px; color: #000; font-weight: normal; font-style: normal; text-decoration: none; font-family: Helvetica,Arial,sans-serif; font-size: 12pt;"><div style="font-family: Aptos, Aptos_EmbeddedFont, Aptos_MSFontService, Calibri, Helvetica, sans-serif; font-size: 12pt; color: #000000;" data-mce-style="font-family: Aptos, Aptos_EmbeddedFont, Aptos_MSFontService, Calibri, Helvetica, sans-serif; font-size: 12pt; color: #000000;"><br></div><div id="Signature"><div style="font-family: Calibri, Arial, Helvetica, sans-serif; font-size: 12pt; color: #000000;" data-mce-style="font-family: Calibri, Arial, Helvetica, sans-serif; font-size: 12pt; color: #000000;">Cheers,<br>√</div><div style="font-family: Calibri, Arial, Helvetica, sans-serif; font-size: 12pt; color: #000000;" data-mce-style="font-family: Calibri, Arial, Helvetica, sans-serif; font-size: 12pt; color: #000000;"><br></div><div style="font-family: Calibri, Arial, Helvetica, sans-serif; font-size: 12pt; color: #000000;" data-mce-style="font-family: Calibri, Arial, Helvetica, sans-serif; font-size: 12pt; color: #000000;"><b><br></b></div><div style="font-family: Calibri, Arial, Helvetica, sans-serif; font-size: 12pt; color: #000000;" data-mce-style="font-family: Calibri, Arial, Helvetica, sans-serif; font-size: 12pt; color: #000000;"><b>Viktor Klang</b></div><div style="font-family: Calibri, Arial, Helvetica, sans-serif; font-size: 12pt; color: #000000;" data-mce-style="font-family: Calibri, Arial, Helvetica, sans-serif; font-size: 12pt; color: #000000;">Software Architect, Java Platform Group<br>Oracle</div></div><hr style="display: inline-block; width: 98%;" data-mce-style="display: inline-block; width: 98%;"><div id="divRplyFwdMsg" dir="ltr"><span style="font-size: 11pt; color: #000000; font-family: Calibri, sans-serif;" data-mce-style="font-size: 11pt; color: #000000; font-family: Calibri, sans-serif;"><b>From:</b> core-libs-dev <core-libs-dev-retn@openjdk.org> on behalf of Remi Forax <forax@univ-mlv.fr><br><b>Sent:</b> Wednesday, 17 January 2024 16:55<br><b>To:</b> core-libs-dev <core-libs-dev@openjdk.java.net><br><b>Subject:</b> Gatherer API : wildcards complaint</span><div> </div></div><div class="BodyFragment"><div class="PlainText">Hello,<br>this is a minor complaint but I do not see a raison to not getting this right.<br><br>Currently the Gatherer API does not use the wildcard correctly, which is not fully an issue because there is "enough" wildcards that if you rely on the inference, it will work.<br><br>The problem is that when you write code, you make mistakes and usually when you have a typing issue, a way to debug it is to fix the type arguments de-activating the inference.<br>But because there are some missing wildcards, this debugging strategy just fail flat with more typing errors.<br><br>I think that fixing the missing wildcards will hep users (or a least me) to have a better experience when using the Gatherer API.<br><br>I can help and propose a PR if you want.<br><br>regards,<br>Rémi<br></div></div><br></blockquote></div></div></body></html>