Так, например, почему List(1,2,3,4).contains("wtf")
даже компилируется? Было бы неплохо, если бы компилятор это отклонил?
Scala: Почему Seq.contains принимает аргумент Any, а не аргумент типа последовательности?
Ответы (3)
Множество интересных ответов, но вот моя собственная теория: если 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 ==)
^
-Xfatal-warnings
, чтобы компиляция не прошла
- person Joan; 09.07.2019
"contains" в основном относится к проверке равенства, а равенство в Scala (как и в Java до него) нетипизировано. Практическая ценность нетипизированного равенства мала, но не равна нулю. Есть, например, несколько случаев, когда имеет смысл, чтобы два объекта разных классов были равны друг другу. Например, вы можете пожелать, чтобы объект типа RGBColor был равен PantoneColor, если они определяют один и тот же оттенок, или неизменяемый HashSet и неизменный TreeSet были равны, если они содержат одинаковые элементы. Тем не менее, нетипизированное равенство также вызывает кучу головных болей, и тот факт, что компилятор мог легко уловить это List(1,2,3,4).contains("wtf")
, бессмысленно, но не будет, является одним из них.
Большинство инструментов для поиска ошибок Java включают тесты для обнаружения невероятных вариантов использования нетипизированного равенства. (Я написал инспекции, чтобы сделать это в IntelliJ IDEA.) Я не сомневаюсь, что когда появятся инструменты поиска ошибок Scala, они будут среди первых обнаруженных ошибок.
List(1,2,3,4).contains(BigInt("2"))
приводит к true
. Лично я думаю, что этого можно было достичь с помощью классов неявных / типов вместо того, чтобы заставлять _3 _ / _ 4_ принимать Any
...
- person soc; 10.09.2010
SeqLike.contains проверяет, присутствует ли значение, проверяя элемент в последовательности, который равен значению (с помощью ==). == принимает Any, поэтому я подозреваю, что это причина.
contains
должен соответствовать общему случаю (когда одинаковые объекты имеют один и тот же тип), поскольку метод exists
может использоваться для реализации более общего теста.
- person Aaron Novstrup; 09.09.2010
==
является эквивалентом Java equals()
в Scala. Как объяснил Дэйв Гриффит, и Java, и Scala используют нетипизированное равенство.
- person Aaron Novstrup; 09.09.2010
Collection<T>.contains
также принимает аргумент типаObject
, а неT
), хотя, по общему признанию, это не так много ответа. - person sepp2k   schedule 09.09.2010