Czy w Scali jest jakaś różnica między Nil
i List()
?
Jeśli nie, to który z nich jest bardziej idiomatyczny w stylu Scala? Zarówno do tworzenia nowych pustych list, jak i dopasowywania wzorców na pustych listach.
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
Brak jest bardziej idiomatyczny i może być preferowany w większości przypadków. Pytania?
Nil
jest to bardziej idiomatyczne.List[A]()
(nieNil
) konieczne jako wartość akumulatora dla foldLeft? Przykład -scala> Map(1 -> "hello", 2 -> "world").foldLeft(List[String]())( (acc, el) => acc :+ el._2) res1: List[String] = List(hello, world)
użycieNil
jako akumulatora tutaj nie zadziała.Map(1 -> "hello", 2 -> "world").foldLeft(Nil: List[String])( _ :+ _._2)
Użytkownik nieznany wykazał, że wartości czasu wykonywania obu
Nil
iList()
są takie same. Jednak ich statyczny typ nie jest: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
Ma to szczególne znaczenie, gdy jest używane do wnioskowania typu, na przykład w akumulatorze fałdy:
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) ^
źródło
y :: x
robi pracę. Problem polega na tym, że typ, który zwraca, nie jest typem oczekiwanym. PowracaList[Int]
, podczas gdy oczekiwany typ to alboList[Nothing]
lubNil.type
(myślę, że pierwszy, ale może drugi).Jak pokazuje odpowiedź nieznanego użytkownika, są to ten sam obiekt.
Idiomatycznie Nil powinno być preferowane, ponieważ jest ładne i krótkie. Jest jednak wyjątek: jeśli z jakiegokolwiek powodu potrzebny jest jawny typ
List[Foo]()
jest ładniejszy niż
Nil : List[Foo]
źródło
List.empty[Foo]
trzecia alternatywa.