Так, например, почему List(1,2,3,4).contains("wtf")
даже компилируется? Было бы неплохо, если бы компилятор отказался от этого?
Scala: Почему Seq.contains принимает любой аргумент, а не аргумент типа последовательности?
Ответ 1
Множество интересных ответов, но вот моя собственная теория: если contains
не получил Any
, то Seq
не мог быть ковариантным.
См., например, Set
, который не является ковариантным и contains
принимает A
вместо Any
.
Причины этого оставлены как упражнение для читателя.;-) Но вот подсказка:
scala> class Container[+A](elements: A*) {
| def contains(what: A): Boolean = elements exists (what ==)
| }
<console>:7: error: covariant type A occurs in contravariant position in type A of value what
def contains(what: A): Boolean = elements exists (what ==)
^
Ответ 2
"содержит" в основном о тестировании равенства, а равенство в Scala (как и в Java перед ним) является нетипизированным. Практическая ценность наличия нетипизированного равенства мала, но не равна нулю. Есть, например, несколько случаев, когда имеет смысл, чтобы два объекта разных классов были равны друг другу. Например, вы можете пожелать, чтобы объект типа RGBColor был равен PantoneColor, если они определяют один и тот же оттенок, или неизменяемый HashSet и неизменяемый TreeSet равны, если они содержат одни и те же элементы. Тем не менее, нетипизированное равенство также вызывает кучу головных болей, и тот факт, что компилятор может легко поймать, что List(1,2,3,4).contains("wtf")
является бессмысленным, но не является одним из них.
Большинство инструментов поиска ошибок Java включают тесты для обнаружения присутствия невероятных применений без аутентификации. (Я написал проверки для этого в IntelliJ IDEA.) Я не сомневаюсь, что когда инструменты поиска ошибок Scala заходят онлайн, они будут среди первых обнаруженных ошибок.
Ответ 3
SeqLike.contains проверяет, присутствует ли значение, проверяя элемент в последовательности, которая равна значению (с использованием ==). == принимает Any, поэтому я подозреваю, что это причина.