<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<style type="text/css" style="display:none;"> P {margin-top:0;margin-bottom:0;} </style>
</head>
<body dir="ltr">
<div class="elementToProof"><span style="font-family: Aptos, Aptos_EmbeddedFont, Aptos_MSFontService, Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">Ah, now I see what you mean! Thank you đŸ‘<br>
<br>
The reason for the signature of `Gatherer.of` was to mirror as much as possible of `Collector.of`[1] so I would argue that if we tweak the variance of one then we should consider tweaking it for both.<br>
<br>
</span></div>
<div class="elementToProof"><span style="font-family: Aptos, Aptos_EmbeddedFont, Aptos_MSFontService, Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">1:</span><span style="font-family: Aptos, Aptos_EmbeddedFont, Aptos_MSFontService, Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);"><a href="https://github.com/openjdk/jdk/blob/master/src/java.base/share/classes/java/util/stream/Collector.java#L264" id="LPlnk890719">https://github.com/openjdk/jdk/blob/master/src/java.base/share/classes/java/util/stream/Collector.java#L264</a></span></div>
<div class="elementToProof" style="font-family: Aptos, Aptos_EmbeddedFont, Aptos_MSFontService, Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
<br>
</div>
<div id="Signature">
<div style="font-family: Calibri, Arial, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
Cheers,<br>
√</div>
<div style="font-family: Calibri, Arial, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
<br>
</div>
<div style="font-family: Calibri, Arial, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
<b><br>
</b></div>
<div style="font-family: Calibri, Arial, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
<b>Viktor Klang</b></div>
<div style="font-family: Calibri, Arial, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
Software Architect, Java Platform Group<br>
Oracle</div>
</div>
<div id="appendonsend"></div>
<hr style="display:inline-block;width:98%" tabindex="-1">
<div id="divRplyFwdMsg" dir="ltr"><font face="Calibri, sans-serif" style="font-size:11pt" color="#000000"><b>From:</b> forax@univ-mlv.fr <forax@univ-mlv.fr><br>
<b>Sent:</b> Wednesday, 17 January 2024 20:49<br>
<b>To:</b> Viktor Klang <viktor.klang@oracle.com><br>
<b>Cc:</b> core-libs-dev <core-libs-dev@openjdk.java.net><br>
<b>Subject:</b> [External] : Re: Gatherer API : wildcards complaint</font>
<div> </div>
</div>
<div>
<div style="font-family:arial,helvetica,sans-serif; font-size:12pt; color:#000000">
<div><br>
</div>
<div><br>
</div>
<hr id="x_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 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;" 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 data-mce-style="font-family: Aptos, Aptos_EmbeddedFont, Aptos_MSFontService, Calibri, Helvetica, sans-serif; font-size: 12pt; color: #000000;" style="font-family:Aptos,Aptos_EmbeddedFont,Aptos_MSFontService,Calibri,Helvetica,sans-serif; font-size:12pt; color:#000000">Hi
 RĂ©mi,</span></div>
<div class="x_elementToProof"><span data-mce-style="font-family: Aptos, Aptos_EmbeddedFont, Aptos_MSFontService, Calibri, Helvetica, sans-serif; font-size: 12pt; color: #000000;" style="font-family:Aptos,Aptos_EmbeddedFont,Aptos_MSFontService,Calibri,Helvetica,sans-serif; font-size:12pt; color:#000000"><br>
</span></div>
<div class="x_elementToProof"><span data-mce-style="font-family: Aptos, Aptos_EmbeddedFont, Aptos_MSFontService, Calibri, Helvetica, sans-serif; font-size: 12pt; color: #000000;" 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 data-mce-style="font-family: Aptos, Aptos_EmbeddedFont, Aptos_MSFontService, Calibri, Helvetica, sans-serif; font-size: 12pt; color: #000000;" 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 data-mce-style="background-color: #ffffff; color: #080808;" style="background-color:#ffffff; color:#080808">
<pre data-mce-style="font-family: 'JetBrains Mono',monospace; font-size: 9.8pt;" style="font-family:'JetBrains Mono',monospace; font-size:9.8pt"><span data-mce-style="color: #0033b3;" style="color:#0033b3">interface </span><span data-mce-style="color: #000000;" style="color:#000000">Counter </span>{<br>  <span data-mce-style="color: #0033b3;" style="color:#0033b3">void </span><span data-mce-style="color: #00627a;" style="color:#00627a">increment</span>();<br>  <span data-mce-style="color: #0033b3;" style="color:#0033b3">int </span><span data-mce-style="color: #00627a;" style="color:#00627a">value</span>();<br>}<br><br><span data-mce-style="color: #000000;" style="color:#000000">Gatherer</span><<span data-mce-style="color: #000000;" style="color:#000000">String</span>, <span data-mce-style="color: #000000;" style="color:#000000">Counter</span>, <span data-mce-style="color: #000000;" style="color:#000000">Integer</span>> <span data-mce-style="color: #00627a;" style="color:#00627a">count</span>() {<br>  <span data-mce-style="color: #0033b3;" style="color:#0033b3">class </span><span data-mce-style="color: #000000;" style="color:#000000">CounterImpl </span><span data-mce-style="color: #0033b3;" style="color:#0033b3">implements </span><span data-mce-style="color: #000000;" style="color:#000000">Counter </span>{<br>    <span data-mce-style="color: #0033b3;" style="color:#0033b3">int </span><span data-mce-style="color: #871094;" style="color:#871094">counter</span>;<br><br>    <span data-mce-style="color: #9e880d;" style="color:#9e880d">@Override<br></span><span data-mce-style="color: #9e880d;" style="color:#9e880d">    </span><span data-mce-style="color: #0033b3;" style="color:#0033b3">public void </span><span data-mce-style="color: #00627a;" style="color:#00627a">increment</span>() {<br>      <span data-mce-style="color: #871094;" style="color:#871094">counter</span>++;<br>    }<br><br>    <span data-mce-style="color: #9e880d;" style="color:#9e880d">@Override<br></span><span data-mce-style="color: #9e880d;" style="color:#9e880d">    </span><span data-mce-style="color: #0033b3;" style="color:#0033b3">public int </span><span data-mce-style="color: #00627a;" style="color:#00627a">value</span>() {<br>      <span data-mce-style="color: #0033b3;" style="color:#0033b3">return </span><span data-mce-style="color: #871094;" style="color:#871094">counter</span>;<br>    }<br>  }<br>  <span data-mce-style="color: #000000;" style="color:#000000">Supplier</span><<span data-mce-style="color: #000000;" style="color:#000000">CounterImpl</span>> <span data-mce-style="color: #000000;" style="color:#000000">initializer </span>= <span data-mce-style="color: #000000;" style="color:#000000">CounterImpl</span>::<span data-mce-style="color: #0033b3;" style="color:#0033b3">new</span>;<br>  <span data-mce-style="color: #000000;" style="color:#000000">Gatherer</span>.<span data-mce-style="color: #000000;" style="color:#000000">Integrator</span><<span data-mce-style="color: #000000;" style="color:#000000">Counter</span>, <span data-mce-style="color: #000000;" style="color:#000000">String</span>, <span data-mce-style="color: #000000;" style="color:#000000">Gatherer</span>.<span data-mce-style="color: #000000;" style="color:#000000">Downstream</span><? <span data-mce-style="color: #0033b3;" style="color:#0033b3">super </span><span data-mce-style="color: #000000;" style="color:#000000">Integer</span>>> <span data-mce-style="color: #000000;" style="color:#000000">integrator </span>= (<span data-mce-style="color: #000000;" style="color:#000000">counter</span>, <span data-mce-style="color: #000000;" style="color:#000000">_</span>, <span data-mce-style="color: #000000;" style="color:#000000">_</span>) -> {<br>    <span data-mce-style="color: #000000;" style="color:#000000">counter</span>.increment();<br>    <span data-mce-style="color: #0033b3;" style="color:#0033b3">return true</span>;<br>  };<br>  <span data-mce-style="color: #000000;" style="color:#000000">BiConsumer</span><<span data-mce-style="color: #000000;" style="color:#000000">Counter</span>, <span data-mce-style="color: #000000;" style="color:#000000">Gatherer</span>.<span data-mce-style="color: #000000;" style="color:#000000">Downstream</span><? <span data-mce-style="color: #0033b3;" style="color:#0033b3">super </span><span data-mce-style="color: #000000;" style="color:#000000">Integer</span>>> <span data-mce-style="color: #000000;" style="color:#000000">finisher </span>= (<span data-mce-style="color: #000000;" style="color:#000000">counter</span>, <span data-mce-style="color: #000000;" style="color:#000000">downstream</span>) -> {<br>    <span data-mce-style="color: #000000;" style="color:#000000">downstream</span>.push(<span data-mce-style="color: #000000;" style="color:#000000">counter</span>.value());<br>  };<br>  <span data-mce-style="color: #8c8c8c; font-style: italic;" style="color:#8c8c8c; font-style:italic"></span><span data-mce-style="color: #0033b3;" style="color:#0033b3">return </span><span data-mce-style="color: #000000;" style="color:#000000">Gatherer</span>.<span data-mce-style="font-style: italic;" style="font-style:italic">ofSequential</span>(<span data-mce-style="color: #000000;" style="color:#000000">initializer</span>, <span data-mce-style="color: #000000;" style="color:#000000">integrator</span>, <span data-mce-style="color: #000000;" style="color:#000000">finisher</span>);    <span data-mce-style="color: #8c8c8c; font-style: italic;" style="color:#8c8c8c; font-style:italic">// does not compile :(</span><span data-mce-style="color: #8c8c8c; font-style: italic;" style="color:#8c8c8c; font-style:italic"></span><br>}<br><br><span data-mce-style="color: #0033b3;" style="color:#0033b3">void </span><span data-mce-style="color: #00627a;" style="color:#00627a">main</span>() {<br><span data-mce-style="color: #000000;" style="color:#000000">  System</span>.<span data-mce-style="color: #871094; font-style: italic;" style="color:#871094; font-style:italic">out</span>.println(<span data-mce-style="color: #000000;" style="color:#000000">Stream</span>.<span data-mce-style="font-style: italic;" style="font-style:italic">of</span>(<span data-mce-style="color: #067d17;" 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 data-mce-style="background-color: #ffffff; color: #080808;" style="background-color:#ffffff; color:#080808">
<pre data-mce-style="font-family: 'JetBrains Mono',monospace; font-size: 9.8pt;" style="font-family:'JetBrains Mono',monospace; font-size:9.8pt"><span data-mce-style="color: #0033b3;" style="color:#0033b3">return </span><span data-mce-style="color: #000000;" style="color:#000000">Gatherer</span>.<span data-mce-style="font-style: italic;" style="font-style:italic">ofSequential</span>(<br>    <span data-mce-style="color: #000000;" style="color:#000000">CounterImpl</span>::<span data-mce-style="color: #0033b3;" style="color:#0033b3">new</span>,<br>    (<span data-mce-style="color: #000000;" style="color:#000000">Counter counter</span>, <span data-mce-style="color: #000000;" style="color:#000000">String _</span>, <span data-mce-style="color: #000000;" style="color:#000000">Gatherer</span>.<span data-mce-style="color: #000000;" style="color:#000000">Downstream</span><? <span data-mce-style="color: #0033b3;" style="color:#0033b3">super </span><span data-mce-style="color: #000000;" style="color:#000000">Integer</span>> <span data-mce-style="color: #000000;" style="color:#000000">_</span>) -> {<br>      <span data-mce-style="color: #000000;" style="color:#000000">counter</span>.increment();<br>      <span data-mce-style="color: #0033b3;" style="color:#0033b3">return true</span>;<br>    },<br>    (<span data-mce-style="color: #000000;" style="color:#000000">Counter counter</span>, <span data-mce-style="color: #000000;" style="color:#000000">Gatherer</span>.<span data-mce-style="color: #000000;" style="color:#000000">Downstream</span><? <span data-mce-style="color: #0033b3;" style="color:#0033b3">super </span><span data-mce-style="color: #000000;" style="color:#000000">Integer</span>> <span data-mce-style="color: #000000;" style="color:#000000">downstream</span>) -> {<br>      <span data-mce-style="color: #000000;" style="color:#000000">downstream</span>.push(<span data-mce-style="color: #000000;" 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 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;" 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 data-mce-style="font-family: Aptos, Aptos_EmbeddedFont, Aptos_MSFontService, Calibri, Helvetica, sans-serif; font-size: 12pt; color: #000000;" style="font-family:Aptos,Aptos_EmbeddedFont,Aptos_MSFontService,Calibri,Helvetica,sans-serif; font-size:12pt; color:#000000">
<br>
</div>
<div id="x_Signature">
<div data-mce-style="font-family: Calibri, Arial, Helvetica, sans-serif; font-size: 12pt; color: #000000;" style="font-family:Calibri,Arial,Helvetica,sans-serif; font-size:12pt; color:#000000">
Cheers,<br>
√</div>
<div data-mce-style="font-family: Calibri, Arial, Helvetica, sans-serif; font-size: 12pt; color: #000000;" style="font-family:Calibri,Arial,Helvetica,sans-serif; font-size:12pt; color:#000000">
<br>
</div>
<div data-mce-style="font-family: Calibri, Arial, Helvetica, sans-serif; font-size: 12pt; color: #000000;" style="font-family:Calibri,Arial,Helvetica,sans-serif; font-size:12pt; color:#000000">
<b><br>
</b></div>
<div data-mce-style="font-family: Calibri, Arial, Helvetica, sans-serif; font-size: 12pt; color: #000000;" style="font-family:Calibri,Arial,Helvetica,sans-serif; font-size:12pt; color:#000000">
<b>Viktor Klang</b></div>
<div data-mce-style="font-family: Calibri, Arial, Helvetica, sans-serif; font-size: 12pt; color: #000000;" style="font-family:Calibri,Arial,Helvetica,sans-serif; font-size:12pt; color:#000000">
Software Architect, Java Platform Group<br>
Oracle</div>
</div>
<hr data-mce-style="display: inline-block; width: 98%;" style="display:inline-block; width:98%">
<div id="x_divRplyFwdMsg" dir="ltr"><span data-mce-style="font-size: 11pt; color: #000000; font-family: Calibri, sans-serif;" 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="x_BodyFragment">
<div class="x_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>
</div>
</body>
</html>