Entonces, por ejemplo, ¿por qué se compila List(1,2,3,4).contains("wtf")
? ¿No sería bueno si el compilador lo rechazara?Scala: ¿Por qué Seq.contains toma un argumento Any, en lugar de un argumento del tipo de secuencia?
Scala: ¿Por qué Seq.contains toma un argumento Any, en lugar de un argumento del tipo de secuencia?
Respuesta
Muchas respuestas interesantes, pero esta es mi propia teoría: si contains
no recibió un , entonces Seq
no podría ser covariante.
Véase, por ejemplo, Set
, que no es co-variante y cuya contains
toma un A
en lugar de un Any
.
Las razones de esto se dejan como un ejercicio para el lector. ;-) Pero aquí hay una pista:
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 ==)
^
Ah. Otros han hecho puntos interesantes (¡gracias a todos!), Pero apuesto a que esta es la verdadera razón. –
Y para responder el "ejercicio para el lector" de Daniel: si Seq es covariante, entonces p. un Seq [Int] debe calificar como Seq [Cualquiera], entonces debo poder pasar cualquier cosa a su método contains. –
Ah, y luego quería saber por qué Set es invariante. Eso se responde aquí: http://stackoverflow.com/questions/676615/why-is-scalas-immutable-set-not-covariant-in-its-type –
SeqLike.contains comprueba si hay un valor presente al buscar un elemento en la secuencia que sea igual al valor (utilizando ==). == toma una Any, así que sospecho que esta es la razón.
Sí, la relación de equivalencia no requiere que dos objetos tengan el mismo tipo. Es discutible que el método 'contains' se adapte al caso común (donde objetos iguales tienen el mismo tipo) ya que el método' exists' podría usarse para implementar una prueba más general. –
Eso no es realmente una razón, ¿verdad? Ha habido una decisión consciente de usar == en lugar de lo que sea el equivalente de Scala de .equals(). Entonces, la verdadera respuesta reside en la decisión más que en la implementación. – dty
@Danny En realidad, '==' * es * el equivalente de Scala de Java 'equals()'. Como Dave Griffith explicó, tanto Java como Scala usan igualdad sin tipo. –
"contiene" es fundamentalmente sobre pruebas de igualdad, y la igualdad en Scala (como en Java antes) está sin tipo. El valor práctico de tener igualdad sin tipo es pequeño, pero no cero. Hay, por ejemplo, algunas ocasiones en las que tiene sentido que dos objetos de diferentes clases sean iguales entre sí. Por ejemplo, puede desear que un objeto de tipo RGBColor sea igual a un PantoneColor si definen el mismo matiz, o un HashSet inmutable y un TreeSet inmutables iguales si contienen los mismos elementos. Dicho esto, la igualdad no tipificada también causa muchos dolores de cabeza, y el hecho de que el compilador pueda detectar fácilmente que List(1,2,3,4).contains("wtf")
es absurdo, pero no lo es.
La mayoría de las herramientas de búsqueda de errores de Java incluyen pruebas para detectar la presencia de improbables usos de igualdad no tipificada. (Escribí las inspecciones para hacer esto en IntelliJ IDEA.) No me cabe duda de que cuando las herramientas de detección de fallas de Scala se conecten, estos se encontrarán entre los primeros errores detectados.
Ah, debería mencionar que si quieres jugar con la igualdad de tipeo en lugar de igualdad sin tipo, echa un vistazo a la construcción Equals en la biblioteca de scalaz. En un mundo perfecto, las colecciones serían parametrizables sobre su predicado de prueba de igualdad, pero en el mundo real las bibliotecas todavía no están allí. –
Un caso de uso que encontré: 'List (1,2,3,4) .contains (BigInt (" 2 "))' da como resultado 'true'. Personalmente, creo que se podría haber logrado con clases de implicits/type en lugar de hacer 'contains' /' exists' tomar 'Any' ... – soc
- 1. ¿Por qué Seq.contains acepta el tipo Any en lugar del parámetro de tipo A?
- 2. ¿Por qué apply() aquí solo toma un argumento en lugar de dos?
- 3. ¿Qué función no toma ningún argumento?
- 4. ¿Por qué debería pop() tomar un argumento?
- 5. ¿Por qué el tipo del argumento var-arg es "aproximado"?
- 6. pasar un tipo como argumento atributo
- 7. Un argumento, muchas funciones
- 8. ¿Por qué Map.containsKey() toma un parámetro Object en lugar de un tipo especializado?
- 9. ¿Por qué el argumento del tipo de mapa C++ requiere un constructor vacío cuando se usa []?
- 10. ANSI C: ¿Por qué las funciones de caracteres aceptan el argumento int en lugar del argumento char?
- 11. ¿Por qué una declaración de función con un argumento const permite llamar a una función con un argumento no const?
- 12. ¿Es posible que un valor de argumento opcional que depende de otro argumento en Scala
- 13. ¿Por qué el constructor EnumMap necesita un argumento de clase?
- 14. OptionParser devolviendo bool en lugar de argumento?
- 15. String.Format() toma una matriz como un solo argumento
- 16. ¿Por qué C "fopen" toma un "const char *" como segundo argumento?
- 17. El tipo de argumento no cumple con CLS, ¿por qué?
- 18. Obteniendo el tipo de argumento en un método
- 19. ¿Por qué declarar que un argumento de función es definitivo?
- 20. ¿Por qué el método Scala's require en Predef permite un String como argumento?
- 21. ¿Se puede pasar un "tipo" como argumento?
- 22. Pasando un tipo Enum como argumento?
- 23. ¿Por qué no puedo usar un argumento de tipo en un parámetro de tipo con múltiples límites?
- 24. ¿Por qué Arrays.sort toma Object [] en lugar de Comparable []?
- 25. ¿Por qué Bourne shell printf itera sobre un argumento% s?
- 26. Argumento booleano para la secuencia de comandos
- 27. Usando bind1st por un método que toma el argumento por referencia
- 28. Constructores con el mismo tipo de argumento
- 29. ¿Por qué CompositionTarget.Rendering toma EventArgs en lugar de RenderingEventArgs?
- 30. ¿Por qué la función requestAnimationFrame acepta un elemento como argumento?
¿La lista es genérica en Scala, por lo que solo acepta elementos de un tipo? –
Probablemente Scala lo hace de esta manera porque así es como lo hace Java ('Collection .contains' también toma un argumento de tipo' Object', no 'T'), aunque admitidamente eso no es una gran respuesta. –
sepp2k