Scala: Nil vs List ()


128

Чи є в Scala різниця між Nilі List()?

Якщо ні, то який із ідіоматичних стилів Scala? І для створення нових порожніх списків, і для відповідності шаблонів у порожніх списках.

Відповіді:


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

Ніл є більш ідіоматичним і в більшості випадків його можна віддати перевагу. Питання?


11
Ви можете згадати, що Nilє більш ідіоматичним.
Рекс Керр

6
Додано System.identityHashCode для уточнення того, що "eq" вже говорить - це той самий об'єкт.
Джеймс Ірі

18
Крім того, Nil посилається на об'єкт безпосередньо, тоді як List () - виклик методу.
Жан-Філіп Пеллет

6
Чи не List[A]()(не Nil) потрібно як значення акумулятора для foldLeft? Приклад - scala> Map(1 -> "hello", 2 -> "world").foldLeft(List[String]())( (acc, el) => acc :+ el._2) res1: List[String] = List(hello, world)Використання Nilяк акумулятора тут не працює.
Кевін Мередіт

6
Map(1 -> "hello", 2 -> "world").foldLeft(Nil: List[String])( _ :+ _._2)
Рауль

85

Користувач невідомо показав, що значення часу виконання обох Nilі List()є однаковим. Однак їх статичний тип не є:

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

Це має особливе значення, коли він використовується для виведення типу, наприклад, у акумуляторі складки:

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

я не розумію, чому 2 :: Nil працює, але не
FUD

2
@FUD Ну, y :: x і працює. Проблема полягає в тому, що тип, який він повертає, не є очікуваним типом. Він повертається List[Int], тоді як очікуваний тип є List[Nothing]або Nil.type(я думаю, перший, але, можливо, останній).
Даніель К. Собрал

27

Як показує відповідь невідомого користувача, вони є одним і тим же об'єктом.

Ідіоматично слід віддати перевагу Нілу, оскільки він приємний і короткий. Однак є виняток: якщо ясний тип потрібен з будь-якої причини, я думаю

List[Foo]() 

приємніше, ніж

Nil : List[Foo]

36
Існує також List.empty[Foo]третя альтернатива.
kassens
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.