#kotlin
Вопрос:
Если я правильно читаю подпись типа, Array.reduce
должен ли я возвращать подкласс типа элемента в массиве? Это кажется совершенно произвольным и ненужным ограничением?
inline fun <S, T : S> Array<out T>.reduce(
operation: (acc: S, T) -> S
): S
Почему это не может быть произвольный класс, такой как:
fun main(params: Array<String>) {
val args = params.reduce(Args(), {accum: Args, arg: String -> accum.parse(arg) })
}
Комментарии:
1. Как вы можете видеть, вам пришлось добавить дополнительный аргумент в свою «более общую»
reduce
функцию. Эта общая функция существует и вызываетсяfold
в Kotlin, и у нее нет ограничений по типу, о которых вы говорите.
Ответ №1:
На самом деле все наоборот: возвращаемый тип должен быть супертипом данных в массиве, а не подтипом. Я не думаю, что это имеет какое-либо отношение к изменчивости.
Причина в том, что на первой итерации первый элемент массива становится накопителем. Поэтому, если массив будет содержать, например, целые числа, но накопитель будет иметь String
тип, этот первый шаг будет невозможен.
fold()
работает по-другому: он получает начальное значение аккумулятора в качестве параметра, поэтому он может быть любого типа.
Ответ №2:
Это потому Array.reduce
, что это не мутирующая редукция. Для уменьшения мутаций вы хотите Array.fold
вместо этого.
Комментарии:
1. Вы могли бы написать мутирующее
reduce
и не мутирующееfold
-это не имеет ничего общего с мутацией, это связано именно с тем, что упоминает OP: fold имеет более общий тип возврата и не нуждается в том, чтобы коллекция была непустой, и он делает это, запрашивая начальное значение аккумулятора.2. @Джоффри Я использую термин «изменяемое сокращение» в том смысле, в каком он используется в документации по сбору Java . Вместо этого Котлин называет это фолдом. Это нормально, просто мне было трудно найти кого-то с опытом работы на Java. Поэтому я решил, что сброшу что-нибудь на ТАК, чтобы люди могли найти.