News for hackers. Stuff that matters.
Re:Background: how we got the generics we have (2020) by vimax on Thursday April 01, 2021 @01:39PM (#26663705)
I want to do something like this:

public <Z, T extends Iterable<Z>, R> T<R> process(T, Function<Z,R>)

change the type parameter of T<Z> to T<R> and return an instance of T<R>, but the best I can do is return an instance of Iterable<R> because I cannot define T to have a type parameter.

Re:Background: how we got the generics we have (2020) by p2t2p on Thursday April 01, 2021 @10:10PM (#26668451)
Sooooo.... A bit more involved than what you describe but I managed to do that:

    public <A, B, T extends Iterable<A>, R extends Iterable<B>> R process(T input, Function<? super A, ? extends B> transformer,
                                                                          Function<Iterable<B>, R> helper) {
        return helper.apply(StreamSupport.stream(input.spliterator(), false)
                .map(transformer)
                .collect(toList()));
    }

    @Test
    public void testProcess() {
        Iterable<Integer> ints = process(Arrays.asList("1", "2", "3"), Integer::parseInt, identity());
        System.out.println(ints);
    }
Outputs nicely integers nicely converted from strings: [1, 2, 3]

:-P

`identity()` is a static import of `Function.identity()`

Re:Background: how we got the generics we have (2020) by vimax on Friday April 02, 2021 @05:13PM (#26676059)
That's close, but not quite what I want. The Iterator example starts to break down, but I want to pass in a subclass of Iteratable and get that subclass back.

class SpecialIterator<R> extends Iterator<R>{}

SpecialIterator<String> strings =...;

SpecialIterator<Integer> ints = process(string, magicFunc);

The Iterator example starts to break down, so here's a more concrete example:

I have 3 classes: AbstractTester, StringTester, and ListTester

class AbstractTester<R, T extends AbstractTester<R, ? super T>>

class StringTester<R> extends AbstractTester<R, StringTester<R>>

class ListTester<R, T extends AbstractTester<R, ? super T>>

I want to make a method in AbstractListTest like this: public <Z> T<Z> convert(Z z)

I have supporting code in my classes to create an return an instance of type T<Z>, but I cannot express the type T<Z> in the type system. The type parameter T can extend something with a type parameter, and be passed a type with a type parameter, but it cannot be defined to have a type parameter itself.

This is for a fluent api framework, where I need the compiler to know the type T<Z> without casting

I can do something like this: public <Z, Y extends AbstractTester<Z, ? super T>> Y convert(Z z);

but that will return an AbstractTester<Z> which can be cast to a StringTester<Z>, but the compiler does not know it is a StringTester<Z>

A subclass of AbstractTester is not required to have any type parameters itself. Converting a T to a T<Z> would not be legal for a T without a type parameter. To do what I want, Java would need to add a new type bounds operator to restrict a type parameter to subclasses with a particular type parameter.

Java would need to allow me to define ListTester like this to restrict T to only subclasses with a type parameter:

class ListTester<R, T<_> extends AbstractTester<_, ? super T<_>>

I'd love to be wrong, and would be very grateful to find a way to do this.

Re:Background: how we got the generics we have (2020) by p2t2p on Thursday April 01, 2021 @10:12PM (#26668460)
The only caveat is that if you change `Iterable<Integer>` to say `Iterable<String>` the compilation error becomes a bit weird in that it says you provide `Iterable<Object>` while `Iterable<String>` is requested. But you do get compile time check after all.
Re:Background: how we got the generics we have (2020) by mrkeen on Friday April 02, 2021 @04:17PM (#26675490)
T is not R though. I want to preserve the static type information such that if I call:

    baz(bar(foo(t, f)));
T<A> should go into foo(..) and come out (e.g. as T<B>) such that I can then call bar(..) on it.

But in this case it leaves foo(..) as R extends Fooable, which is not something I can pass into bar(..).

Re:Background: how we got the generics we have (2020) by zeroimpl on Friday April 02, 2021 @05:25PM (#26676169)
I’d just solve this by passing in a Class<S extends Iterable<R>> arg and making the returned list be an instance of this class, instead of forcing the input collection type to be the same as the output collection type.
Re:Background: how we got the generics we have (2020) by mrkeen on Saturday April 03, 2021 @04:16PM (#26684359)
Then I can't chain method calls.

    foo.doSomething()      // returns Iterable.
       .doSomethingElse(); // Iterable doesn't implement doSomethingElse();
Re:Background: how we got the generics we have (2020) by mrkeen on Thursday April 01, 2021 @05:59PM (#26666688)
This comment explains my problem much better than I did.
Re:Background: how we got the generics we have (2020) by vimax on Friday April 02, 2021 @05:22PM (#26676142)
See my other comment for a longer explanation.

I'm curious what your were working on where you ran into this?

Re:Background: how we got the generics we have (2020) by mrkeen on Saturday April 03, 2021 @04:31PM (#26684451)
* At a previous job, I needed to change a fairly large codebase from using Guava futures to Java 8 futures.

* At the same job, a coworker expressed a desire to rewrite it with Observables.

* At a different job, a different coworker rewrote a chunk of code from Observables into futures.

* At my current job, we use micronaut, which has announced it's switching from rxjava2 to project reactor.

In the above cases, having interfaces would really help in changing the code piece-by-piece. And the rewrites wouldn't be necessary if they were behind interfaces.

In the general case I just want to program to the interface, and not pin my business logic to any particular implementation.

Re:Background: how we got the generics we have (2020) by p2t2p on Thursday April 01, 2021 @10:13PM (#26668467)
see my comment for the parent with _a_ solution =)