Scala: Почему Seq.contains принимает аргумент Any вместо аргумента типа последовательности? - PullRequest
22 голосов
/ 09 сентября 2010

Так, например, почему List(1,2,3,4).contains("wtf") даже компилируется?Разве не было бы хорошо, если бы компилятор отклонил это?

Ответы [ 3 ]

21 голосов
/ 09 сентября 2010

Множество интересных ответов, но вот моя собственная теория: если 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 ==)
                      ^
4 голосов
/ 09 сентября 2010

«содержит» в основном о тестировании на равенство, и равенство в Scala (как и в Java до него) не типизировано. Практическая ценность наличия нетипизированного равенства мала, но не равна нулю. Есть, например, несколько случаев, когда два объекта разных классов имеют смысл быть равными друг другу. Например, вы можете пожелать, чтобы объект типа RGBColor был равен PantoneColor, если они определяют один и тот же оттенок, или неизменный HashSet и неизменный TreeSet равны, если они содержат одинаковые элементы. Тем не менее, нетипизированное равенство также вызывает кучу головных болей, и тот факт, что компилятор может легко уловить, что List(1,2,3,4).contains("wtf") бессмысленно, но не будет, является одним из них.

Большинство инструментов для поиска ошибок Java включают в себя тесты, чтобы обнаружить наличие неправдоподобных применений с нетипизированным равенством. (Я написал проверки для этого в IntelliJ IDEA.) Я не сомневаюсь, что когда инструменты поиска ошибок Scala появятся в сети, они будут одними из первых обнаруженных ошибок.

1 голос
/ 09 сентября 2010

SeqLike.contains проверяет, присутствует ли значение, проверяя наличие элемента в последовательности, равной значению (используя ==) == принимает Any, поэтому я подозреваю, что это причина.

...