Scala: Nil vs List ()


128

In Scala, c'è qualche differenza tra Nile List()?

In caso contrario, quale è lo stile Scala più idiomatico? Sia per la creazione di nuovi elenchi vuoti sia per la corrispondenza dei modelli su elenchi vuoti.

Risposte:


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

Lo zero è più idiomatico e può essere preferito nella maggior parte dei casi. Domande?


11
Potresti dire che Nilè più idiomatico.
Rex Kerr,

6
Aggiunto System.identityHashCode per chiarire cosa dice già "eq": sono lo stesso oggetto.
James Iry,

18
Inoltre, Nil fa riferimento direttamente a un oggetto, mentre List () è una chiamata di metodo.
Jean-Philippe Pellet,

6
Non è List[A]()(non Nil) necessario come valore dell'accumulatore per foldLeft? Esempio - L' scala> Map(1 -> "hello", 2 -> "world").foldLeft(List[String]())( (acc, el) => acc :+ el._2) res1: List[String] = List(hello, world)uso Nilcome accumulatore qui non funzionerebbe.
Kevin Meredith,

6
Map(1 -> "hello", 2 -> "world").foldLeft(Nil: List[String])( _ :+ _._2)
Raul,

85

L'utente sconosciuto ha dimostrato che il valore di runtime di entrambi Nile List()sono gli stessi. Tuttavia, il loro tipo statico non è:

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

Ciò è di particolare importanza quando viene utilizzato per inferire un tipo, come nell'accumulatore di una piega:

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)
                                               ^

non capisco perché 2 :: Nil funziona ma non accumulatore fold y :: x
FUD

2
@FUD Beh, y :: x fa il lavoro. Il problema è che il tipo che restituisce non è il tipo previsto. Restituisce List[Int], mentre il tipo previsto è o List[Nothing]o Nil.type(penso il primo, ma forse il secondo).
Daniel C. Sobral,

27

Come mostra la risposta dell'utente sconosciuto, sono lo stesso oggetto.

Idiomaticamente zero dovrebbe essere preferito perché è bello e corto. C'è comunque un'eccezione: se è necessario un tipo esplicito per qualsiasi motivo, penso

List[Foo]() 

è più bello di

Nil : List[Foo]

36
C'è anche List.empty[Foo]una terza alternativa.
Kasens,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.