Mengapa hampir di semua bahasa pemrograman modern (Go, Rust, Kotlin, Swift, Scala, Nim, bahkan versi terakhir Python) selalu muncul setelah nama variabel dalam deklarasi variabel, dan bukan sebelumnya?
Kenapa x: int = 42
dan tidak int x = 42
?
Apakah yang terakhir tidak lebih mudah dibaca daripada yang pertama?
Apakah ini hanya tren atau adakah alasan yang benar-benar bermakna di balik solusi ini?
programming-languages
language-design
syntax
Andre Polykanine
sumber
sumber
Jawaban:
Semua bahasa yang Anda sebutkan inferensi tipe dukungan , yang berarti tipe tersebut adalah bagian opsional dari deklarasi dalam bahasa-bahasa tersebut karena mereka cukup pintar untuk mengisinya sendiri ketika Anda memberikan ekspresi inisialisasi yang memiliki tipe yang mudah ditentukan.
Itu penting karena menempatkan bagian opsional ekspresi lebih jauh ke kanan mengurangi ambiguitas penguraian, dan meningkatkan konsistensi antara ekspresi yang menggunakan bagian itu dan yang tidak. Hanya lebih mudah untuk mengurai deklarasi ketika Anda tahu
var
kata kunci dan nama variabel keduanya wajib sebelum Anda sampai ke hal-hal opsional. Secara teori, semua hal yang membuatnya lebih mudah diurai untuk komputer harus meningkatkan keterbacaan keseluruhan bagi manusia juga, tapi itu jauh lebih bisa diperdebatkan.Argumen ini menjadi sangat kuat ketika Anda mempertimbangkan semua pengubah tipe opsional yang dimiliki bahasa "non-modern" seperti C ++, seperti
*
untuk pointer,&
untuk referensiconst
,,volatile
dan sebagainya. Setelah Anda melemparkan koma untuk beberapa deklarasi, Anda mulai mendapatkan beberapa ambiguitas yang sangat aneh sepertiint* a, b;
tidak membuatb
pointer.Bahkan C ++ sekarang mendukung deklarasi "ketik di kanan" dalam bentuk
auto x = int{ 4 };
, dan itu memang memiliki beberapa keunggulan .sumber
var
itu memberikan mayoritas penyederhanaan parsing.var
kata kunci mengalahkan tujuan notasi nama-pertama? Saya tidak melihat keuntungan dari menulisvar userInput: String = getUserInput()
lebihString userInput = getUserInput()
. Keuntungannya hanya akan relevan jikauserInput = getUserInput()
juga diizinkan, tetapi itu akan menyiratkan pernyataan implisit dari variabel scoped, yang menurut saya cukup menjijikkan.var userInput = getUserInput()
atauauto userInput = getUserInput()
, kompiler tahu akangetUserInput()
kembaliString
sehingga Anda tidak harus menentukannya dengan jenis kata kunci pengurangan.userInput = getUserInput()
tentu saja digunakan sebelum menyatakan.Premis Anda cacat di dua bidang:
Pascal, ML, CLU, Modula-2, dan Miranda semuanya adalah bahasa yang sangat berpengaruh, sehingga tidak mengherankan bahwa gaya deklarasi tipe ini tetap populer.
Keterbacaan adalah masalah keakraban. Secara pribadi, saya menemukan bahasa Mandarin tidak dapat dibaca, tetapi ternyata, orang-orang Tionghoa tidak. Setelah mempelajari Pascal di sekolah, mencoba-coba Eiffel, F♯, Haskell, dan Scala, dan setelah melihat TypeScript, Fortress, Go, Rust, Kotlin, Idris, Frege, Agda, ML, Ocaml,…, itu terlihat sangat alami bagi saya .
Jika tren, itu cukup gigih: seperti yang saya sebutkan, itu kembali seratus tahun dalam matematika.
Salah satu keuntungan utama memiliki jenis setelah pengidentifikasi, adalah mudah untuk meninggalkan jenis jika Anda ingin disimpulkan. Jika deklarasi Anda terlihat seperti ini:
Maka sepele untuk meninggalkan jenis dan disimpulkan seperti ini:
Sedangkan jika jenisnya datang sebelum pengenal seperti ini:
Kemudian mulai menjadi sulit bagi parser untuk membedakan ekspresi dari deklarasi:
Solusi yang biasanya muncul oleh perancang bahasa adalah dengan memperkenalkan kata kunci "Saya tidak ingin menulis jenis" yang harus ditulis alih-alih jenis:
Tapi ini sebenarnya tidak masuk akal: Anda pada dasarnya harus secara eksplisit menulis jenis yang mengatakan bahwa Anda tidak menulis jenis. Hah? Akan jauh lebih mudah dan lebih masuk akal untuk meninggalkannya, tetapi itu membuat tata bahasanya jauh lebih kompleks.
(Dan mari kita bahkan tidak berbicara tentang jenis pointer fungsi di C.)
Para perancang dari beberapa bahasa yang disebutkan di atas telah mempertimbangkan masalah ini:
Go FAQ (lihat juga: Go's Declaration Syntax ):
FAQ Kotlin :
Pemrograman dalam Scala :
Catatan: desainer Ceylon juga mendokumentasikan mengapa mereka menggunakan sintaks tipe awalan :
Secara pribadi, saya menemukan "argumen" mereka jauh kurang meyakinkan daripada yang lain.
sumber
var
,auto
,let
, atau sejenisnya, bukan oleh sisi mana variabel deklarasi tipe aktif.var Int x = 5
atau bahkanInt var x = 5
keduanya bisa disingkatvar x = 5
."Your premise is flawed on two fronts"
Semua itu lebih baru dari C # atau D.func
di Go.Omong-omong, Pascal juga melakukannya, dan bukan bahasa baru. Itu adalah bahasa akademis, dirancang dari awal.
Saya akan mengatakan secara semantik lebih jelas untuk memulai dengan nama variabel. Jenisnya hanyalah detail teknis. Jika Anda ingin membaca kelas Anda seperti model kenyataan yang ada, masuk akal untuk menempatkan nama entitas Anda terlebih dahulu dan implementasi teknisnya yang terakhir.
C # dan java berasal dari C sehingga mereka harus menghormati "prior art", jadi tidak membingungkan programmer yang berpengalaman.
sumber
Dalam contoh sederhana seperti itu, tidak ada banyak perbedaan, tetapi mari kita buat sedikit lebih rumit:
int* a, b;
Ini adalah deklarasi aktual dan valid dalam C, tetapi tidak melakukan apa yang seharusnya dilakukan secara intuitif. Sepertinya kita mendeklarasikan dua variabel tipe
int*
, tetapi sebenarnya kita mendeklarasikan satuint*
dan satuint
.Jika bahasa Anda menempatkan tipe setelah nama variabel dalam deklarasi, masalah itu tidak mungkin terjadi.
sumber
x, y *int;
dua*int
atau satu*int
dan satuint
? Membuatint*
atau*int
satu token alih-alih dua akan menyelesaikannya, atau menggunakan elemen sintaksis tambahan seperti:
, yang dapat bekerja di kedua arah.:
atauas
, antara nama dan jenisnya.x, y int
tanpa pemisah.x, y *int
berarti "mendeklarasikan dua variabel, x dan y, dengan tipe pointer-to-int".int[] x, y
sebagai dua array. Hanya sintaks konyol C yang memperlakukan pengubah tersebut sebagai operator unary pada variabel (dan campuran awalan dan postfix, tidak kurang) yang menyebabkan masalah.