Penggunaan Null / Nothing / Unit di Scala

95

Saya baru saja membaca: http://oldfashionedsoftware.com/2008/08/20/a-post-about-nothing/

Sejauh yang saya mengerti, itu Nulladalah sifat dan satu-satunya contoh adalah null.

Ketika sebuah metode mengambil argumen Null, maka kita hanya dapat meneruskannya sebagai Nullreferensi atau nullsecara langsung, tetapi tidak untuk referensi lain, meskipun nilainya null ( nullString: String = nullmisalnya).

Saya hanya ingin tahu dalam kasus mana menggunakan Nullsifat ini dapat berguna. Ada juga sifat Tidak Ada yang tidak benar-benar saya lihat contohnya.


Saya juga tidak begitu mengerti apa perbedaan antara menggunakan Nothing dan Unit sebagai tipe pengembalian, karena keduanya tidak mengembalikan hasil apa pun, bagaimana cara mengetahui mana yang akan digunakan ketika saya memiliki metode yang melakukan logging misalnya?


Apakah Anda memiliki penggunaan Unit / Null / Nothing sebagai sesuatu yang lain selain tipe pengembalian?

Sebastien Lorber
sumber

Jawaban:

80

Anda hanya menggunakan Nothing jika metode tersebut tidak pernah kembali (artinya tidak dapat diselesaikan secara normal dengan mengembalikannya, metode ini dapat memunculkan pengecualian). Tidak ada yang tidak pernah dibuat dan ada untuk kepentingan sistem tipe (mengutip James Iry: "Alasan Scala memiliki tipe terbawah terkait dengan kemampuannya untuk mengekspresikan varians dalam parameter tipe." ). Dari artikel yang Anda tautkan:

Satu kegunaan lain dari Nothing adalah sebagai tipe pengembalian untuk metode yang tidak pernah kembali. Masuk akal jika Anda memikirkannya. Jika tipe kembalian sebuah metode adalah Nothing, dan sama sekali tidak ada turunan dari Nothing, maka metode seperti itu tidak boleh kembali.

Metode logging Anda akan mengembalikan Unit. Ada Satuan nilai sehingga benar-benar dapat dikembalikan. Dari dokumen API :

Unit adalah subtipe dari scala.AnyVal. Hanya ada satu nilai bertipe Unit, (), dan tidak diwakili oleh objek apa pun dalam sistem runtime yang mendasarinya. Metode dengan tipe pengembalian Unit analog dengan metode Java yang dinyatakan batal.

Nathan Hughes
sumber
2
Terima kasih, dengan "tidak pernah kembali", maksud Anda panggilan tersebut memblokir tanpa batas waktu (misalnya, metode startup penjadwal pekerjaan?)
Sebastien Lorber
3
@Sabastien: itu tidak kembali secara normal, itu bisa membuat pengecualian (lihat james-iry.blogspot.com/2009/08/… ). jika panggilan pemblokiran hanya diakhiri dengan mengeluarkan pengecualian maka itu akan dihitung. terima kasih atas pertanyaannya, ini perlu klarifikasi.
Nathan Hughes
18

Artikel yang Anda kutip bisa menyesatkan. The Nulljenis ada untuk kompatibilitas dengan mesin virtual Java , dan Jawa pada khususnya.

Kita harus mempertimbangkan Scala itu :

  • sepenuhnya berorientasi objek: setiap nilai adalah objek
  • diketik dengan kuat: setiap nilai harus memiliki tipe
  • perlu menangani nullreferensi untuk mengakses, misalnya, pustaka dan kode Java

dengan demikian menjadi perlu untuk mendefinisikan tipe untuk nullnilai, yang merupakan Nullsifat, dan nullsebagai satu-satunya contoh.

Tidak ada yang sangat berguna dalam Nulltipe kecuali Anda adalah tipe-sistem atau Anda sedang mengembangkan pada compiler. Secara khusus saya tidak dapat melihat alasan yang masuk akal untuk menentukan Nullparameter tipe untuk suatu metode, karena Anda tidak dapat melewatkan apa pun kecualinull

pagoda_5b
sumber
itu benar, jadi pada akhirnya tidak ada penggunaan lain dari Null?
Sebastien Lorber
@SebastienLorber mengedit jawabannya. Saya tidak dapat benar-benar melihat penggunaan apa pun untuk pengembang rata-rata. Mungkin orang lain bisa memikirkan sesuatu yang berguna.
pagoda_5b
Terima kasih untuk ini. Jika kita mengetahui alasan untuk hal-hal semacam ini, kita memahaminya, jika tidak kita akan mengingatnya.
Sreekar
Null berguna ketika Anda memiliki parameter tipe dan mungkin ingin mengembalikan null seperti dalam pertanyaan dan jawaban ini , karena Anda tidak disarankan menggunakan null dalam skala, meskipun jarang muncul, mungkin ada penggunaan lain dalam sistem tipe juga
Daniel Carlsson
15

Apakah Anda memiliki penggunaan Unit / Null / Nothing sebagai sesuatu yang lain selain tipe pengembalian?


Unit bisa digunakan seperti ini:

def execute(code: => Unit):Unit = {
  // do something before
  code
  // do something after
}

Ini memungkinkan Anda untuk mengirimkan blok kode arbitrer untuk dieksekusi.


Nulldapat digunakan sebagai tipe bawah untuk nilai apa pun yang nihil. Contohnya begini:

implicit def zeroNull[B >: Null] =
    new Zero[B] { def apply = null }

Nothing digunakan dalam definisi None

object None extends Option[Nothing]

Ini memungkinkan Anda untuk menetapkan Nonejenis apa pun Optionkarena Nothing'memperluas' segalanya.

val x:Option[String] = None
EECOLOR
sumber
Baik. Untuk penggunaan Unit Anda, Anda dapat menggunakan tipe generik sehingga eksekusi dapat mengembalikan tipe generik ini jika blok kode Anda mengembalikan sesuatu selain unit.
Sebastien Lorber
Seperti yang dikatakan @drexin dalam komentar di jawaban lain, ini sebagian besar digunakan untuk menunjukkan efek samping.
EECOLOR
6

jika Anda menggunakan Nothing, tidak ada yang harus dilakukan (termasuk konsol cetak) jika Anda melakukan sesuatu, gunakan tipe keluaranUnit

object Run extends App {
  //def sayHello(): Nothing = println("hello?")
  def sayHello(): Unit = println("hello?")
  sayHello()
}

... lalu bagaimana cara menggunakannya Nothing?

trait Option[E]
case class Some[E](value: E) extends Option[E]
case object None extends Option[Nothing]
Curycu
sumber
1
Juga, Edalam Optionharus dalam posisi kovarian: trait Option[+E]untuk memungkinkan hal-hal sepertival x: Option[Int] = None
vim
5

Saya tidak pernah benar-benar menggunakan Nulltipe tersebut, tetapi Anda menggunakan Unit, di mana Anda akan menggunakan java void. Nothingadalah tipe khusus, karena seperti yang telah disebutkan Nathan, tidak ada contoh Nothing. Nothingadalah apa yang disebut tipe bawah, yang berarti, itu adalah sub-tipe dari tipe lain. Ini (dan parameter tipe kontravarian) adalah mengapa Anda dapat menambahkan nilai apa pun ke Nil- yang merupakan a List[Nothing]- dan daftar kemudian akan menjadi jenis elemen ini. Nonejuga jika tipe Option[Nothing]. Setiap upaya untuk mengakses nilai di dalam wadah seperti itu akan memunculkan pengecualian, karena itulah satu-satunya cara yang valid untuk kembali dari metode tipe Nothing.

drexin
sumber
terima kasih Saya tidak tahu bahwa Tidak ada yang memperluas Opsi [Tidak ada]. Masuk akal dalam beberapa penggunaan generik di mana subtipe dapat menggunakan Nothing (saya kira sulit untuk menemukan contoh untuk Null dan Unit ...)
Sebastien Lorber
Unit digunakan, di mana efek samping terjadi, misalnya monad IO dapat digunakan IO[Unit]untuk mencetak ke konsol dan sejenisnya.
drexin
Ya, tidak pernah menggunakan monad IO, masuk akal untuk menggunakannya dengan Unit (dan mungkin Tidak ada jika itu adalah operasi IO yang menghasilkan aliran tak terbatas?)
Sebastien Lorber
Tidak, Tidak ada yang tidak masuk akal di sana.
drexin
3

Tidak ada yang sering digunakan secara implisit. Dalam kode di bawah, val b: Boolean = if (1 > 2) false else throw new RuntimeException("error") yang lain klausa adalah tipe ada , yang merupakan subclass dari Boolean (serta setiap AnyVal lainnya). Dengan demikian, keseluruhan tugas valid untuk kompilator, meskipun klausa else tidak benar-benar mengembalikan apa pun.

Fang Zhang
sumber
1

Berikut contoh Nothingdari scala.predef:

  def ??? : Nothing = throw new NotImplementedError

Jika Anda tidak terbiasa (dan mesin pencari tidak dapat mencarinya) ???adalah fungsi placeholder Scala untuk apa pun yang belum diimplementasikan. Sama seperti Kotlin TODO.

Anda dapat menggunakan trik yang sama saat membuat objek tiruan: ganti metode yang tidak digunakan dengan metode khusus notUsed. Keuntungan tidak menggunakan ???adalah Anda tidak akan mendapatkan peringatan kompilasi untuk hal-hal yang tidak ingin Anda implementasikan.

David Leppik
sumber
0

Dari segi teori kategori Tidak ada objek awal dan Unit adalah objek terminal .

https://en.wikipedia.org/wiki/Initial_and_terminal_objects

Objek awal juga disebut koterminal atau universal , dan objek terminal juga disebut akhir .

Jika sebuah objek adalah inisial dan terminal , itu disebut objek nol atau objek nol .

Joe
sumber