RxKotlin collectInto() MutableList с использованием ссылок на методы

Следующий код - моя попытка преобразовать пример RxJava в Kotlin. Это должно собрать кучу Intв MutableList, но я получаю массу ошибок.

val all: Single<MutableList<Int>> = Observable
        .range(10, 20)
        .collectInto(::MutableList, MutableList::add)

Ошибки:

    Error:(113, 36) Kotlin: Type inference failed: Not enough information to infer parameter T in inline fun <T> MutableList(size: Int, init: (index: Int) -> T): MutableList<T>
Please specify it explicitly.

Error:(113, 49) Kotlin: One type argument expected for interface MutableList<E> : List<E>, MutableCollection<E> defined in kotlin.collections

    Error:(113, 67) Kotlin: None of the following functions can be called with the arguments supplied: 
public abstract fun add(element: Int): Boolean defined in kotlin.collections.MutableList
public abstract fun add(index: Int, element: Int): Unit defined in kotlin.collections.MutableList

Если я изменю ImmutableList::add в ImmutableList<Int>::addЯ избавляюсь от аргумента типа ожидаемой ошибки, который заменяется на:

Error:(113, 22) Kotlin: Type inference failed: fun <U : Any!> collectInto(initialValue: U!, collector: ((U!, Int!) -> Unit)!): Single<U!>!
        cannot be applied to
        (<unknown>,<unknown>)

Это прямая копия следующего в Java:

Observable<List<Integer>> all = Observable
    .range(10, 20)
    .collect(ArrayList::new, List::add);

Я понимаю, что первая ошибка говорит мне, что это либо неверный тип, и мне нужно быть более точным (где?), Но я подумал, что ::MutableList будет эквивалентно () -> MutableList<Int>, Третья ошибка говорит мне, что он не может вызвать add() методы с аргументами, но опять же я думал, что MutableList::add эквивалентно { list, value -> list.add(value) }, Четвертая ошибка говорит мне, что она не может определить типы, применяемые к collector,

Если я вместо этого использую лямбда-выражение, ошибок нет:

val all: Single<MutableList<Int>> = Observable
        .range(10, 20)
        .collectInto(mutableListOf(), { list, value -> list.add(value) })

all.subscribe { x -> println(x) }

Я был бы признателен за некоторые комментарии о том, что я делаю неправильно со ссылками на методы, поскольку я явно что-то не так понял (просматривая справочник по языку Kotlin, мне интересно, есть ли в настоящее время даже языковая функция?). Очень признателен.

1 ответ

Решение

В первом примере вы пытаетесь применить сигнатуру метода collect одному из collectInto,

Это никогда не может работать, так как collect ожидает Func0<R> и Action2<R, ? super T> а также collectInto ожидает реальный объект и BiConsumer<U, T>,
Ссылка на конструктор не может работать для collectInto - вам нужен реальный объект (например, ваш mutableListOf() вызов)

Вторая проблема заключается в том, что Котлин ожидает BiConsumer объект, а не функция. Я не совсем уверен, почему. Очевидно, что Kotlin не может обрабатывать несколько обобщений для лямбда-ссылок и ссылки на функции из SAM-интерфейсов.

Поэтому вам нужно передать экземпляр BiConsumer а не просто функция.
Вот почему я спросил в комментарии, уверены ли вы в сообщении об ошибке:

range(10, 20).collectInto(mutableListOf(), { l, i ->  l.add(i) }) 

выдаст мне ошибку, пока

range(10, 20).collectInto(mutableListOf(), BiConsumer { l, i ->  l.add(i) })

не будет.

Другие вопросы по тегам