Почему Array.reduce должен возвращать подкласс?

#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. Поэтому я решил, что сброшу что-нибудь на ТАК, чтобы люди могли найти.