Saya yakin perancang bahasa seperti Java atau C # tahu masalah yang terkait dengan keberadaan referensi nol (lihat Apakah referensi nol benar-benar buruk? ). Juga menerapkan jenis opsi tidak benar-benar jauh lebih kompleks daripada referensi nol.
Mengapa mereka memutuskan untuk memasukkannya? Saya yakin kurangnya referensi nol akan mendorong (atau bahkan memaksa) kode kualitas yang lebih baik (terutama desain perpustakaan yang lebih baik) baik dari pembuat bahasa dan pengguna.
Apakah itu hanya karena konservatisme - "bahasa lain memilikinya, kita harus memilikinya juga ..."?
language-design
null
mrpyo
sumber
sumber
Jawaban:
Penafian: Karena saya tidak mengenal perancang bahasa secara pribadi, jawaban apa pun yang saya berikan kepada Anda akan spekulatif.
Dari Tony Hoare sendiri:
Tekankan milikku.
Tentu saja itu bukan ide yang buruk baginya saat itu. Kemungkinan itu telah diabadikan sebagian karena alasan yang sama - jika sepertinya ide yang bagus untuk penemu quicksort pemenang Penghargaan Turing, tidak mengherankan bahwa banyak orang masih tidak mengerti mengapa itu jahat. Mungkin juga sebagian karena bahasa baru yang digunakan mirip dengan bahasa yang lebih lama, baik karena alasan pemasaran dan kurva pembelajaran. Inti masalah:
(Sumber: http://www.paulgraham.com/icad.html )
Dan, tentu saja, C ++ memiliki nol karena C memiliki nol, dan tidak perlu masuk ke dampak historis C. Jenis C # menggantikan J ++, yang merupakan implementasi Microsoft dari Java, dan itu juga menggantikan C ++ sebagai bahasa pilihan untuk pengembangan Windows, jadi itu bisa didapat dari salah satunya.
Sunting Berikut ini kutipan lain dari Hoare yang patut dipertimbangkan:
Sekali lagi, tekankan saya. Sun / Oracle dan Microsoft adalah perusahaan, dan garis bawah perusahaan mana pun adalah uang. Manfaat bagi mereka karena
null
mungkin lebih besar daripada kontra, atau mereka mungkin memiliki tenggat waktu yang terlalu ketat untuk sepenuhnya mempertimbangkan masalah tersebut. Sebagai contoh kesalahan bahasa yang berbeda yang mungkin terjadi karena tenggat waktu:(Sumber: http://www.artima.com/intv/bloch13.html )
sumber
null
dalam bahasanya? Setiap jawaban untuk pertanyaan ini akan bersifat spekulatif kecuali berasal dari perancang bahasa. Saya tidak tahu ada yang sesering ini di situs ini selain Eric Lippert. Bagian terakhir adalah herring merah karena berbagai alasan. Jumlah kode pihak ke-3 yang ditulis di atas MS dan API Java jelas melebihi jumlah kode dalam API itu sendiri. Jadi, jika pelanggan Anda menginginkannyanull
, Anda memberi merekanull
. Anda juga mengira mereka telah menerimanull
biaya mereka uang.ICloneable
juga rusak di. NET; sayangnya ini adalah satu tempat di mana kekurangan Jawa tidak dipelajari dari waktu ke waktu.Tentu saja.
Saya mohon untuk berbeda! Pertimbangan desain yang masuk ke tipe nilai nullable di C # 2 adalah kompleks, kontroversial dan sulit. Mereka mengambil tim desain dari kedua bahasa dan runtime berbulan-bulan debat, implementasi prototipe, dan sebagainya, dan pada kenyataannya semantik tinju nullable diubah sangat sangat dekat dengan pengiriman C # 2.0, yang sangat kontroversial.
Semua desain adalah proses memilih di antara banyak tujuan yang tidak kompatibel secara halus dan sangat; Saya hanya bisa memberikan sketsa singkat dari beberapa faktor yang akan dipertimbangkan:
Fitur ortogonalitas bahasa umumnya dianggap sebagai hal yang baik. C # memiliki tipe nilai nullable, tipe nilai non-nullable, dan tipe referensi nullable. Tipe referensi yang tidak dapat dibatalkan tidak ada, yang membuat sistem tipe tidak orthogonal.
Keakraban dengan pengguna C, C ++ dan Java yang ada adalah penting.
Interoperabilitas yang mudah dengan COM adalah penting.
Interoperabilitas yang mudah dengan semua bahasa .NET lainnya adalah penting.
Interoperabilitas yang mudah dengan database adalah penting.
Konsistensi semantik penting; jika kita memiliki referensi TheKingOfFrance sama dengan nol apakah itu selalu berarti "tidak ada Raja Prancis saat ini", atau dapatkah itu juga berarti "Jelas ada Raja Prancis; Aku hanya tidak tahu siapa itu sekarang"? atau dapatkah itu berarti "gagasan memiliki seorang Raja di Prancis itu tidak masuk akal, jadi jangan bertanya!"? Null dapat berarti semua hal ini dan lebih banyak lagi dalam C #, dan semua konsep ini berguna.
Biaya kinerja penting.
Menjadi setuju dengan analisis statis adalah penting.
Konsistensi sistem tipe adalah penting; dapatkah kita selalu tahu bahwa referensi yang tidak dapat dibatalkan tidak pernah dalam keadaan apapun dianggap tidak valid? Bagaimana dengan konstruktor objek dengan bidang tipe referensi yang tidak dapat dibatalkan? Bagaimana dengan di finalizer dari objek seperti itu, di mana objek tersebut diselesaikan karena kode yang seharusnya mengisi referensi melemparkan pengecualian ? Jenis sistem yang berbohong kepada Anda tentang jaminannya berbahaya.
Dan bagaimana dengan konsistensi semantik? Null nilai merambat ketika digunakan, tapi nol referensi membuang pengecualian bila digunakan. Itu tidak konsisten; Apakah inkonsistensi itu dibenarkan oleh sejumlah manfaat?
Bisakah kita mengimplementasikan fitur tanpa merusak fitur lain? Apa fitur lain yang mungkin ada di masa depan yang tidak termasuk dalam fitur ini?
Anda pergi berperang dengan tentara yang Anda miliki, bukan yang Anda inginkan. Ingat, C # 1.0 tidak memiliki obat generik, jadi berbicara
Maybe<T>
sebagai alternatif adalah non-starter lengkap. Haruskah .NET tergelincir selama dua tahun sementara tim runtime menambahkan obat generik, semata-mata untuk menghilangkan referensi nol?Bagaimana dengan konsistensi sistem tipe? Anda dapat mengatakan
Nullable<T>
untuk semua tipe nilai - tidak, tunggu, itu bohong. Anda tidak bisa mengatakannyaNullable<Nullable<T>>
. Haruskah kamu bisa? Jika demikian, apa yang diinginkan semantiknya? Apakah bermanfaat membuat seluruh sistem jenis memiliki kasus khusus di dalamnya hanya untuk fitur ini?Dan seterusnya. Keputusan-keputusan ini rumit.
sumber
catches
yang tidak melakukan apa-apa. Saya pikir lebih baik membiarkan sistem meledak daripada melanjutkan operasi dalam kondisi yang mungkin tidak valid.Null memiliki tujuan yang sangat valid untuk mewakili kurangnya nilai.
Saya akan mengatakan saya adalah orang yang paling vokal yang saya tahu tentang penyalahgunaan nol dan semua sakit kepala dan penderitaan yang dapat mereka sebabkan terutama ketika digunakan secara bebas.
Sikap pribadi saya adalah orang dapat menggunakan nulls hanya ketika mereka dapat membenarkan itu perlu dan sesuai.
Contoh justifikasi nol:
Tanggal Kematian biasanya adalah bidang yang tidak dapat dibatalkan. Ada tiga kemungkinan situasi dengan tanggal kematian. Entah orang itu telah meninggal dan tanggalnya diketahui, orang itu telah meninggal dan tanggalnya tidak diketahui, atau orang itu tidak mati dan karenanya tanggal kematian tidak ada.
Date of Death juga merupakan bidang DateTime dan tidak memiliki nilai "tidak dikenal" atau "kosong". Itu memang memiliki tanggal default yang muncul ketika Anda membuat datetime baru yang bervariasi berdasarkan bahasa yang digunakan, tetapi secara teknis ada kemungkinan orang itu benar-benar mati pada waktu itu dan akan ditandai sebagai "nilai kosong" Anda jika Anda ingin gunakan tanggal default.
Data perlu mewakili situasi dengan benar.
Orang meninggal Tanggal kematian diketahui (3/9/1984)
Sederhana, '3/9/1984'
Orang meninggal Tanggal kematian tidak diketahui
Jadi apa yang terbaik? Null , '0/0/0000', atau '01 / 01/1869 '(atau apa pun nilai default Anda?)
Orang tidak mati, tanggal kematian tidak berlaku
Jadi apa yang terbaik? Null , '0/0/0000', atau '01 / 01/1869 '(atau apa pun nilai default Anda?)
Jadi mari kita pikirkan setiap nilai lebih dari ...
Faktanya kadang-kadang Anda Apakah perlu untuk mewakili apa-apa dan yakin kadang-kadang jenis variabel bekerja dengan baik untuk itu, tapi jenis sering variabel harus mampu mewakili apa-apa.
Jika saya tidak memiliki apel, saya memiliki 0 apel, tetapi bagaimana jika saya tidak tahu berapa banyak apel yang saya miliki?
Bagaimanapun, null dilecehkan dan berpotensi berbahaya, tetapi kadang-kadang diperlukan. Ini hanya default dalam banyak kasus karena sampai saya memberikan nilai, kurangnya nilai dan sesuatu yang perlu untuk mewakilinya. (Batal)
sumber
Null serves a very valid purpose of representing a lack of value.
Suatu tipeOption
atauMaybe
melayani tujuan yang sangat valid ini tanpa melewati sistem tipe.NOT NULL
. Pertanyaan saya tidak terkait dengan RDBMS ...Person
tipe memilikistate
bidang tipeState
, yang merupakan serikat terdiskriminasiAlive
danDead(dateOfDeath : Date)
.Saya tidak akan pergi sejauh "bahasa lain memilikinya, kita harus memilikinya juga ..." seperti itu semacam mengikuti keluarga Jones. Fitur utama dari setiap bahasa baru adalah kemampuan untuk beroperasi dengan perpustakaan yang ada dalam bahasa lain (baca: C). Karena C memiliki null pointer, lapisan interoperabilitas tentu membutuhkan konsep nol (atau setara lainnya "tidak ada" yang meledak ketika Anda menggunakannya).
Perancang bahasa bisa memilih untuk menggunakan Jenis Opsi dan memaksa Anda untuk menangani jalur nol di mana - mana hal itu bisa menjadi nol. Dan itu hampir pasti akan menyebabkan lebih sedikit bug.
Tetapi (terutama untuk Java dan C # karena waktu pengenalan mereka dan audiens target mereka) menggunakan jenis opsi untuk lapisan interoperabilitas ini mungkin akan membahayakan jika tidak menghentikan adopsi mereka. Entah jenis opsi diteruskan, mengganggu programer C ++ dari pertengahan hingga akhir 90-an - atau lapisan interoperabilitas akan melempar pengecualian ketika menemukan nol, mengganggu keluar dari programmer C ++ dari pertengahan hingga akhir 90-an. ..
sumber
Option
untuk digunakan dalam Scala, yang semudah ituval x = Option(possiblyNullReference)
. Dalam prakteknya, itu tidak butuh waktu lama bagi orang untuk melihat manfaat dariOption
.Match
metode yang menggunakan delegasi sebagai argumen. Kemudian Anda meneruskan ekspresi lambda keMatch
(poin bonus untuk menggunakan argumen bernama) danMatch
memanggil yang benar.Pertama-tama, saya pikir kita semua bisa sepakat bahwa konsep pembatalan diperlukan. Ada beberapa situasi di mana kita perlu mewakili ketiadaan informasi.
Mengizinkan
null
referensi (dan petunjuk) hanya satu implementasi dari konsep ini, dan mungkin yang paling populer meskipun diketahui memiliki masalah: C, Java, Python, Ruby, PHP, JavaScript, ... semua menggunakan yang serupanull
.Mengapa Nah, apa alternatifnya?
Dalam bahasa fungsional seperti Haskell Anda memiliki
Option
atauMaybe
ketik; namun itu dibangun di atas:Sekarang, apakah C, Java, Python, Ruby, atau PHP yang asli mendukung salah satu fitur itu? Tidak. Generik Java yang cacat baru - baru ini dalam sejarah bahasa dan entah bagaimana saya ragu yang lain bahkan mengimplementasikannya sama sekali.
Itu dia.
null
itu mudah, tipe data aljabar parametrik lebih sulit. Orang-orang mencari alternatif paling sederhana.sumber
Object
" gagal untuk mengenali bahwa aplikasi praktis membutuhkan objek yang bisa dibagikan yang tidak dibagi dan objek yang dapat diubah yang dapat dibagi (keduanya harus berperilaku seperti nilai), serta dapat dibagi dan tidak dapat dibagi entitas. Menggunakan satuObject
tipe untuk semuanya tidak menghilangkan kebutuhan untuk perbedaan seperti itu; itu hanya membuatnya lebih sulit untuk menggunakannya dengan benar.Tidak ada / tidak ada itu sendiri tidak jahat.
Jika Anda menyaksikan pidachnya yang terkenal menyesatkan bernama "The Billion dollar Kesalahan", Tony Hoare berbicara tentang bagaimana membiarkan variabel apa pun untuk dapat menahan nol adalah kesalahan besar. Alternatif - menggunakan Opsi - sebenarnya tidak menghilangkan referensi nol. Alih-alih itu memungkinkan Anda menentukan variabel mana yang diizinkan untuk menahan nol, dan mana yang tidak.
Sebenarnya, dengan bahasa modern yang menerapkan penanganan pengecualian yang tepat, kesalahan null dereference tidak berbeda dari pengecualian lain - Anda menemukannya, Anda memperbaikinya. Beberapa alternatif untuk referensi nol (pola Objek Null misalnya) menyembunyikan kesalahan, menyebabkan semuanya gagal diam-diam sampai jauh kemudian. Menurut pendapat saya, lebih baik gagal cepat .
Jadi pertanyaannya adalah, mengapa bahasa gagal mengimplementasikan Opsi? Sebagai soal fakta, bahasa C ++ yang bisa dibilang paling populer sepanjang masa memiliki kemampuan untuk mendefinisikan variabel objek yang tidak dapat ditugaskan
NULL
. Ini adalah solusi untuk "masalah nol" Tony Hoare yang disebutkan dalam pidatonya. Mengapa bahasa yang diketik paling populer berikutnya, Java, tidak memilikinya? Orang mungkin bertanya mengapa ia memiliki begitu banyak kekurangan secara umum, terutama dalam sistem tipenya. Saya tidak berpikir Anda dapat benar-benar mengatakan bahwa bahasa secara sistematis membuat kesalahan ini. Ada yang melakukannya, ada yang tidak.sumber
null
.null
adalah satu-satunya standar yang masuk akal. Referensi yang digunakan untuk merangkum nilai, bagaimanapun, dapat memiliki perilaku default yang masuk akal dalam kasus di mana suatu tipe akan memiliki atau dapat membangun instance default yang masuk akal. Banyak aspek tentang bagaimana referensi harus berperilaku tergantung pada apakah dan bagaimana mereka merangkum nilai, tetapi ...foo
memegang satu-satunya referensi untuk sebuahint[]
berisi{1,2,3}
dan kode inginfoo
menyimpan referensi ke sebuahint[]
berisi{2,2,3}
, cara tercepat untuk mencapai itu adalah dengan peningkatanfoo[0]
. Jika kode ingin membiarkan suatu metode tahu bahwa metode itufoo
berlaku{1,2,3}
, metode lain tidak akan mengubah array atau mempertahankan referensi di luar titik di mana Andafoo
ingin memodifikasinya, cara tercepat untuk mencapai itu adalah dengan mengirimkan referensi ke array. Jika Java memiliki tipe "referensi baca-saja yang sementara", maka ...Karena bahasa pemrograman pada umumnya dirancang agar praktis bermanfaat daripada benar secara teknis. Faktanya adalah bahwa
null
keadaan adalah kejadian umum karena data yang buruk atau hilang atau keadaan yang belum diputuskan. Solusi yang secara teknis unggul semuanya lebih sulit daripada hanya membiarkan keadaan nol dan menyedot fakta bahwa programmer membuat kesalahan.Misalnya, jika saya ingin menulis skrip sederhana yang berfungsi dengan file, saya bisa menulis pseudocode seperti:
dan itu hanya akan gagal jika joebloggs.txt tidak ada. Masalahnya adalah, untuk skrip sederhana yang mungkin oke dan untuk banyak situasi dalam kode yang lebih kompleks saya tahu itu ada dan kegagalan tidak akan terjadi sehingga memaksa saya untuk memeriksa buang-buang waktu saya. Alternatif yang lebih aman mencapai keselamatan mereka dengan memaksa saya untuk berurusan dengan keadaan potensi kegagalan dengan benar, tetapi seringkali saya tidak ingin melakukan itu, saya hanya ingin melanjutkan.
sumber
for line in file
) dan melempar pengecualian referensi nol yang tidak berarti, yang OK untuk program yang sederhana namun menyebabkan masalah debugging nyata dalam sistem yang jauh lebih kompleks. Jika nulls tidak ada, perancang "openfile" tidak akan dapat membuat kesalahan ini.let file = something(...).unwrap()
. Bergantung pada POV Anda, ini adalah cara mudah untuk tidak menangani kesalahan atau pernyataan singkat bahwa null tidak dapat terjadi. Waktu yang terbuang adalah minimal, dan Anda menghemat waktu di tempat lain karena Anda tidak perlu mencari tahu apakah sesuatu dapat menjadi nol. Keuntungan lain (yang dengan sendirinya bernilai panggilan ekstra) adalah bahwa Anda secara eksplisit mengabaikan kasus kesalahan; ketika gagal ada sedikit keraguan apa yang salah dan ke mana perbaikan harus pergi.if file exists { open file }
menderita kondisi balapan. Satu-satunya cara yang dapat diandalkan untuk mengetahui apakah membuka file akan berhasil adalah dengan mencoba membukanya.Ada penggunaan yang jelas dan praktis dari pointer
NULL
(ataunil
, atauNil
, ataunull
,Nothing
atau apa pun namanya dalam bahasa pilihan Anda).Untuk bahasa-bahasa yang tidak memiliki sistem pengecualian (misalnya C) pointer nol dapat digunakan sebagai tanda kesalahan ketika pointer harus dikembalikan. Sebagai contoh:
Di sini,
NULL
kembali darimalloc(3)
digunakan sebagai penanda kegagalan.Ketika digunakan dalam argumen metode / fungsi, ini dapat menunjukkan penggunaan default untuk argumen atau mengabaikan argumen output. Contoh di bawah ini.
Bahkan untuk bahasa-bahasa dengan mekanisme pengecualian, sebuah null pointer dapat digunakan sebagai indikasi kesalahan lunak (yaitu, kesalahan yang dapat dipulihkan) terutama ketika penanganan pengecualian mahal (misalnya Objective-C):
Di sini, kesalahan lunak tidak menyebabkan program macet jika tidak tertangkap. Ini menghilangkan try-catch gila seperti yang dimiliki Java dan memiliki kontrol yang lebih baik dalam aliran program karena kesalahan lunak tidak mengganggu (dan beberapa pengecualian keras yang tersisa biasanya tidak dapat dipulihkan dan tidak tertangkap)
sumber
null
dari yang seharusnya. Sebagai contoh, jika saya ingin tipe baru yang berisi 5 nilai di Java, saya bisa menggunakan enum, tapi yang saya dapatkan adalah tipe yang bisa menampung 6 nilai (nilai 5 yang saya inginkan +null
). Ini cacat dalam sistem tipe.Null
hanya dapat diberi arti ketika nilai-nilai dari suatu jenis tidak membawa data (misalnya nilai enum). Segera setelah nilai Anda lebih rumit (mis. Sebuah struct),null
tidak dapat diberi arti yang masuk akal untuk jenis itu. Tidak ada cara untuk menggunakannull
sebagai struct atau daftar. Dan, sekali lagi, masalah dengan menggunakannull
sebagai sinyal kesalahan adalah bahwa kita tidak bisa mengatakan apa yang mungkin mengembalikan nol atau menerima nol. Variabel apa pun dalam program Anda bisa menjadinull
kecuali Anda sangat teliti untuk memeriksa setiap satunull
sebelum setiap penggunaan, yang tidak ada yang melakukannya.null
sebagai nilai default yang dapat digunakan (misalnya memiliki nilai defaultstring
berperilaku sebagai string kosong, seperti yang dilakukan di bawah Common Object Model sebelumnya). Semua yang diperlukan akan digunakan untuk bahasacall
daripadacallvirt
saat memanggil anggota non-virtual.Ada dua masalah terkait, tetapi sedikit berbeda:
null
ada? Atau haruskah Anda selalu menggunakanMaybe<T>
mana null berguna?Haruskah semua referensi dibatalkan? Jika tidak, yang mana yang seharusnya menjadi default?
Harus secara eksplisit menyatakan jenis referensi yang dapat dibatalkan sebagai
string?
atau serupa akan menghindari sebagian besar (tetapi tidak semua)null
penyebab masalah , tanpa menjadi terlalu berbeda dari apa yang digunakan oleh programmer.Saya setidaknya setuju dengan Anda bahwa tidak semua referensi harus dibatalkan. Tetapi menghindari null bukan tanpa kerumitannya:
.NET menginisialisasi semua bidang
default<T>
sebelum dapat diakses oleh kode terkelola terlebih dahulu. Ini berarti bahwa untuk tipe referensi yang Anda butuhkannull
atau sesuatu yang setara dan bahwa tipe nilai dapat diinisialisasi ke semacam nol tanpa menjalankan kode. Meskipun keduanya memiliki kelemahan parah, kesederhanaandefault
inisialisasi mungkin lebih penting daripada kerugian tersebut.Untuk bidang Misalnya Anda bisa menyiasatinya dengan mengharuskan inisialisasi bidang sebelum mengekspos
this
pointer ke kode dikelola. Spec # menggunakan rute ini, menggunakan sintaks yang berbeda dari rangkaian konstruktor dibandingkan dengan C #.Untuk bidang statis memastikan ini lebih sulit, kecuali jika Anda mengajukan batasan kuat pada jenis kode apa yang dapat berjalan di penginisialisasi bidang karena Anda tidak bisa menyembunyikan
this
pointer.Bagaimana cara menginisialisasi array tipe referensi? Pertimbangkan
List<T>
yang didukung oleh array dengan kapasitas lebih besar dari panjangnya. Elemen yang tersisa harus memiliki beberapa nilai.Masalah lain adalah bahwa itu tidak memungkinkan metode seperti
bool TryGetValue<T>(key, out T value)
yang kembalidefault(T)
seolah-value
olah mereka tidak menemukan apa pun. Meskipun dalam kasus ini mudah untuk berpendapat bahwa parameter out adalah desain yang buruk di tempat pertama dan metode ini harus mengembalikan serikat diskriminatif atau mungkin sebagai gantinya.Semua masalah ini dapat diselesaikan, tetapi tidak semudah "melarang nol dan semuanya baik-baik saja".
sumber
List<T>
adalah IMHO contoh terbaik, karena akan mengharuskan setiapT
memiliki nilai default, bahwa setiap item di toko dukungan menjadiMaybe<T>
dengan bidang "isValid" tambahan, bahkan ketikaT
aMaybe<U>
, atau bahwa kode untukList<T>
berperilaku berbeda tergantung apakahT
itu sendiri adalah tipe nullable. Saya akan mempertimbangkan inisialisasiT[]
elemen ke nilai default untuk menjadi yang paling jahat dari pilihan itu, tetapi tentu saja berarti bahwa elemen harus memiliki nilai default.Sebagian besar bahasa pemrograman yang berguna memungkinkan item data untuk ditulis dan dibaca dalam urutan yang sewenang-wenang, sehingga seringkali tidak mungkin untuk secara statis menentukan urutan di mana membaca dan menulis akan terjadi sebelum suatu program dijalankan. Ada banyak kasus di mana kode sebenarnya akan menyimpan data yang berguna ke setiap slot sebelum membacanya, tetapi di mana membuktikan itu akan sulit. Dengan demikian, akan sering diperlukan untuk menjalankan program di mana setidaknya secara teori dimungkinkan untuk mencoba membaca sesuatu yang belum ditulis dengan nilai yang bermanfaat. Apakah kode itu legal atau tidak, tidak ada cara umum untuk menghentikan kode dari upaya tersebut. Satu-satunya pertanyaan adalah apa yang harus terjadi ketika itu terjadi.
Bahasa dan sistem yang berbeda mengambil pendekatan yang berbeda.
Salah satu pendekatan akan mengatakan bahwa setiap upaya untuk membaca sesuatu yang belum ditulis akan memicu kesalahan langsung.
Pendekatan kedua adalah meminta kode untuk menyediakan beberapa nilai di setiap lokasi sebelum dimungkinkan untuk membacanya, bahkan jika tidak ada cara agar nilai yang disimpan itu berguna secara semantik.
Pendekatan ketiga adalah mengabaikan masalah dan membiarkan apa pun yang terjadi "secara alami" terjadi begitu saja.
Pendekatan keempat adalah mengatakan bahwa setiap jenis harus memiliki nilai default, dan setiap slot yang belum ditulis dengan yang lain akan default ke nilai itu.
Pendekatan # 4 jauh lebih aman daripada pendekatan # 3, dan secara umum lebih murah daripada pendekatan # 1 dan # 2. Itu kemudian meninggalkan pertanyaan tentang apa nilai default seharusnya untuk tipe referensi. Untuk tipe referensi yang tidak berubah, dalam banyak kasus akan masuk akal untuk mendefinisikan instance default, dan mengatakan bahwa default untuk variabel apa pun dari tipe itu harus menjadi referensi ke instance tersebut. Namun, untuk jenis referensi yang dapat berubah, itu tidak akan sangat membantu. Jika suatu upaya dilakukan untuk menggunakan jenis referensi yang bisa berubah sebelum ditulis, biasanya tidak ada tindakan yang aman selain menjebak pada titik penggunaan yang dicoba.
Secara semantik, jika seseorang memiliki larik
customers
tipeCustomer[20]
, dan satu upayaCustomer[4].GiveMoney(23)
tanpa menyimpan apa pun untukCustomer[4]
, eksekusi harus terperangkap. Orang dapat berargumen bahwa upaya untuk membacaCustomer[4]
harus menjebak segera, daripada menunggu sampai kode mencobaGiveMoney
, tetapi ada cukup kasus di mana itu berguna untuk membaca slot, mengetahui bahwa itu tidak memiliki nilai, dan kemudian memanfaatkannya informasi, bahwa upaya membaca sendiri gagal sering menjadi gangguan besar.Beberapa bahasa memungkinkan seseorang menentukan bahwa variabel tertentu tidak boleh mengandung nol, dan segala upaya untuk menyimpan nol harus memicu jebakan segera. Itu adalah fitur yang bermanfaat. Secara umum, bagaimanapun, bahasa apa pun yang memungkinkan pemrogram untuk membuat array referensi akan harus memungkinkan untuk kemungkinan elemen array nol, atau memaksa inisialisasi elemen array ke data yang tidak mungkin bermakna.
sumber
Maybe
/Option
jenis memecahkan masalah dengan # 2, karena jika Anda tidak memiliki nilai untuk referensi Anda belum tapi akan memiliki satu di masa depan, Anda hanya dapat menyimpanNothing
dalamMaybe <Ref type>
?null
dengan benar / masuk akal?List<T>
aT[]
atau aMaybe<T>
? Bagaimana dengan jenis dukungan aList<Maybe<T>>
?Maybe
masuk akalList
karenaMaybe
memegang nilai tunggal. Apakah maksud AndaMaybe<T>[]
?Nothing
hanya dapat ditugaskan untuk nilai tipeMaybe
, jadi tidak seperti menugaskannull
.Maybe<T>
danT
dua tipe berbeda.