On Wed, 8 Nov 2023 17:11:39 GMT, Rémi Forax <fo...@openjdk.org> wrote:

>> The API should be client-friendly, not implementor-friendly, given that it's 
>> expected to have much more clients than implementors. An implementor can 
>> easily delegate to a private method to add missing type parameters. I did 
>> exactly this in the 
>> [teeing](https://github.com/openjdk/jdk/blob/7d25f1c6cb770e21cfad8096c1637a24e65fab8c/src/java.base/share/classes/java/util/stream/Collectors.java#L1913)
>>  Collector before. There should not be a reason to expose a parameter, which 
>> is merely an implementation detail. This also complicates the public 
>> documentation of the already complex feature, specifying the parameter which 
>> is not necessary to specify. 
>> 
>>> Has this proven to be a problem for things like 
>>> [Collectors.mapping(…)](https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/util/stream/Collectors.html#mapping(java.util.function.Function,java.util.stream.Collector))
>>>  ?
>> 
>> I'm not sure how I can prove this, given that you don't usually know the 
>> downstream accumulator, so if somebody hits this problem, they will be 
>> forced to solve it in another way (e.g., extracting parts of complex 
>> collector to separate variables), so you won't find the code in the wild 
>> which uses `mapping` type arguments explicitly. Yes, `Collectors.mapping` 
>> and `groupingBy` did this mistake in the past, and there's no reason to 
>> repeat it again.
>> 
>>> Do you have a concrete example of where the current "encoding" causes a 
>>> caller-problem?
>> 
>> For example, I want to create a reusable gatherer that performs scan-concat 
>> and wraps every resulting string with '[...]'. First try:
>> 
>> 
>> var gatherer = Gatherers.scan(() -> "", String::concat)
>>   .andThen(Gatherer.ofSequential((_, t, pusher) -> 
>> pusher.push(STR."[{t}]")));
>> 
>> 
>> Now, the type of `gatherer` is `Gatherer<String, ?, Object>`, but I want 
>> `Gatherer<String, ?, String>`. I have the following alternatives:
>> 1. Specify the variable type explicitly:
>> 
>> Gatherer<String, ?, String> gatherer = Gatherers.scan(() -> "", 
>> String::concat)
>>     .andThen(Gatherer.ofSequential((_, t, pusher) -> 
>> pusher.push(STR."[{t}]")));
>> 
>> 2. Specify `ofSequential` type arguments:
>> 
>> var gatherer = Gatherers.scan(() -> "", String::concat)
>>     .andThen(Gatherer.<String, String>ofSequential((_, t, pusher) -> 
>> pusher.push(STR."[{t}]")));
>> 
>> 3. Specify the types of lambda arguments explicitly:
>> 
>> var gatherer = Gatherers.scan(() -> "", String::concat)
>>     .andThen(Gatherer.ofSequential((Void _, String t, Downstream<? super 
>> String> pusher) ->...
>
> I agree with Tagir here, it should be an ? and if you want to capture it in a 
> type variable you can use the standard trick of having the private method 
> declaring the type variable and the public method with the wildcard calling 
> the private method.

Sold! Type argument removed!

-------------

PR Review Comment: https://git.openjdk.org/jdk/pull/16420#discussion_r1387774512

Reply via email to