Scala: Nil vs List ()


128

En Scala, ¿hay alguna diferencia entre Nily List()?

Si no, ¿cuál es el estilo de Scala más idiomático? Tanto para crear nuevas listas vacías como para la coincidencia de patrones en listas vacías.

Respuestas:


188
scala> println (Nil == List())
true

scala> println (Nil eq List())
true

scala> println (Nil equals List())
true

scala> System.identityHashCode(Nil)
374527572

scala> System.identityHashCode(List())
374527572

Nil es más idiomático y se puede preferir en la mayoría de los casos. Preguntas?


11
Se podría mencionar que Niles más idiomático.
Rex Kerr

66
Se agregó System.identityHashCode para aclarar lo que ya dice "eq": son el mismo objeto.
James Iry

18
Además, Nil hace referencia a un objeto directamente, mientras que List () es una llamada al método.
Jean-Philippe Pellet

66
¿No es List[A]()(no Nil) necesario como valor acumulador para foldLeft? Ejemplo: el scala> Map(1 -> "hello", 2 -> "world").foldLeft(List[String]())( (acc, el) => acc :+ el._2) res1: List[String] = List(hello, world)uso Nilcomo acumulador aquí no funcionaría.
Kevin Meredith

66
Map(1 -> "hello", 2 -> "world").foldLeft(Nil: List[String])( _ :+ _._2)
Raúl

85

Usuario desconocido ha demostrado que el valor de tiempo de ejecución de ambos Nily List()son los mismos. Sin embargo, su tipo estático no es:

scala> val x = List()
x: List[Nothing] = List()

scala> val y = Nil
y: scala.collection.immutable.Nil.type = List()

scala> def cmpTypes[A, B](a: A, b: B)(implicit ev: A =:= B = null) = if (ev eq null) false else true
cmpTypes: [A, B](a: A, b: B)(implicit ev: =:=[A,B])Boolean

scala> cmpTypes(x, y)
res0: Boolean = false

scala> cmpTypes(x, x)
res1: Boolean = true

scala> cmpTypes(y, y)
res2: Boolean = true

Esto es de particular importancia cuando se usa para inferir un tipo, como en el acumulador de un pliegue:

scala> List(1, 2, 3).foldLeft(List[Int]())((x, y) => y :: x)
res6: List[Int] = List(3, 2, 1)

scala> List(1, 2, 3).foldLeft(Nil)((x, y) => y :: x)
<console>:10: error: type mismatch;
 found   : List[Int]
 required: scala.collection.immutable.Nil.type
       List(1, 2, 3).foldLeft(Nil)((x, y) => y :: x)
                                               ^

no entiendo por qué 2 :: Nil funciona pero no el acumulador de pliegues y :: x
FUD

2
@FUD Bueno, y :: x hace el trabajo. El problema es que el tipo que devuelve no es el tipo esperado. Regresa List[Int], mientras que el tipo esperado es List[Nothing]o Nil.type(creo que el primero, pero tal vez el último).
Daniel C. Sobral

27

Como muestra la respuesta del usuario desconocido, son el mismo objeto.

Idiomáticamente, se debe preferir Nil porque es agradable y corto. Sin embargo, hay una excepción: si se necesita un tipo explícito por cualquier razón, creo

List[Foo]() 

es mejor que

Nil : List[Foo]

36
También hay List.empty[Foo]una tercera alternativa.
Kassens
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.