Scala: Nil vs List ()

128

Dalam Scala, apakah ada perbedaan sama sekali antara Nildan List()?

Jika tidak, gaya Scala mana yang lebih idiomatis? Baik untuk membuat daftar kosong baru dan pencocokan pola pada daftar kosong.

Bart
sumber

Jawaban:

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 lebih idiomatik dan dapat lebih disukai dalam banyak kasus. Pertanyaan?

Pengguna tidak diketahui
sumber
11
Anda bisa mengatakan itu Nillebih idiomatis.
Rex Kerr
6
Ditambahkan System.identityHashCode untuk mengklarifikasi apa yang "eq" sudah katakan - mereka objek yang sama.
James Iry
18
Selain itu, Nil merujuk objek secara langsung, sedangkan List () adalah pemanggilan metode.
Jean-Philippe Pellet
6
Bukankah List[A]()(tidak Nil) diperlukan sebagai nilai akumulator untuk foldLeft? Contoh - scala> Map(1 -> "hello", 2 -> "world").foldLeft(List[String]())( (acc, el) => acc :+ el._2) res1: List[String] = List(hello, world)Menggunakan Nilsebagai akumulator di sini tidak akan berfungsi.
Kevin Meredith
6
Map(1 -> "hello", 2 -> "world").foldLeft(Nil: List[String])( _ :+ _._2)
Raul
85

Pengguna yang tidak dikenal telah menunjukkan bahwa nilai waktu berjalan keduanya Nildan List()sama. Namun, tipe statis mereka bukan:

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

Ini sangat penting ketika digunakan untuk menyimpulkan suatu tipe, seperti dalam akumulator lipatan:

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)
                                               ^
Daniel C. Sobral
sumber
saya tidak mengerti mengapa 2 :: Nil bekerja tetapi bukan akumulator lipat y :: x
FUD
2
@FUD Nah, y :: x tidak bekerja. Masalahnya adalah bahwa jenis yang dikembalikan bukan jenis yang diharapkan. Itu kembali List[Int], sementara jenis yang diharapkan adalah salah satu List[Nothing]atau Nil.type(saya pikir yang pertama, tapi mungkin yang terakhir).
Daniel C. Sobral
27

Seperti yang ditunjukkan oleh jawaban yang tidak diketahui pengguna, mereka adalah objek yang sama.

Secara nihil Nil harus dipilih karena bagus dan pendek. Namun ada pengecualian: jika jenis eksplisit diperlukan untuk alasan apa pun yang saya pikirkan

List[Foo]() 

lebih baik daripada

Nil : List[Foo]
James Iry
sumber
36
Ada juga List.empty[Foo]sebagai alternatif ketiga.
kassens