Почему оператор Kotlin Iterable minus возвращает только результат без первого вхождения одноэлементного операнда?

#kotlin #operators

#kotlin #операторы

Вопрос:

 public operator fun <T> Iterable<T>.minus(element: T): List<T>
  

Возвращает список, содержащий все элементы исходной коллекции без первого вхождения данного [элемента] .

Это означает, что вычитание одного элемента дает результат, отличный от вычитания списка того же элемента.

Итак

 assertEquals(listOf(2, 1), listOf(1, 2, 1) - 1)
  

тогда как

 assertEquals(listOf(2), listOf(1, 2, 1) - listOf(1))
  

что кажется странным. Почему несоответствие?
Я имею в виду, почему версия элемента удаляет только первое совпадение, а версия списка удаляет каждое совпадение.

Комментарии:

1. Без канонического ответа от разработчиков мы можем только догадываться. Но версию minus (список) было бы трудно описать и рассуждать, если бы ее алгоритм каким-то образом приводил к удалению только первых вхождений элементов. Например, что произойдет, если элемент появится несколько раз в одном или обоих списках? В нынешнем виде это довольно просто: вычитание элемента удаляет один элемент, вычитание коллекции удаляет все, что появляется в коллекции, и точно так же, как filterNot with contains .

Ответ №1:

В вашем втором примере используется другая реализация minus оператора — та, которая принимает an Iterable<T> в качестве параметра, в документе довольно ясно указана разница:

 /**
 * Returns a list containing all elements of the original collection except the elements contained in the given [elements] collection.
 * 
 * The [elements] collection may be converted to a [HashSet] to speed up the operation, thus the elements are required to have
 * a correct and stable implementation of `hashCode()` that doesn't change between successive invocations.
 */
public operator fun <T> Iterable<T>.minus(elements: Iterable<T>): List<T> 
  

Смотрите также: https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/minus.html

Я думаю, вы могли бы утверждать, что семантика the .minus(element: T) настолько отличается от семантики of .minus(elements: Iterable<T>) (и других «коллекционных» типов), чтобы оправдать другое имя функции. Похоже, разработчики библиотеки не думали, что это проблема.

Комментарии:

1. Ах, спасибо, что вы запутались — я обновил свой вопрос, чтобы попытаться сделать его более понятным