Rust: var kata kunci hanya untuk penduduk lokal yang bisa berubah

Dibuat pada 20 Jun 2012  ·  35Komentar  ·  Sumber: rust-lang/rust

Edisi #1273 mengusulkan let mut untuk penduduk lokal yang bisa berubah dan mut untuk bidang yang bisa berubah. let mut lebih bertele-tele daripada satu kata kunci dan juga merusak perataan kolom. Orang benar tidak menyukai gagasan var untuk deklarasi bidang yang bisa berubah. Tapi saya pikir tidak ada yang menyarankan ide menggunakan var untuk deklarasi lokal yang bisa berubah dan mut untuk deklarasi bidang yang bisa berubah:

let x = 7; // declaration of immutable variable x
var y = 7; // declaration of mutable variable y
type point = { mut x: int, mut y: int }; // declaration of mutable record type

Dave

I-nominated

Semua 35 komentar

Harus saya akui, pada awalnya saya berpikir bahwa kita harus menggunakan kata kunci yang sama untuk vars yang bisa berubah dan bidang yang bisa berubah, tetapi var membaca dengan baik (walaupun saya tidak suka let mut )

Saya pikir ini adalah fitur yang mendeklarasikan variabel yang dapat berubah sedikit lebih rumit daripada yang tidak dapat diubah. Saya dapat melihat pemrogram hanya menggunakan "var" untuk menjadi "konsisten" atau karena "var" akan lebih kuat (tidak perlu mengubahnya jika Anda memutuskan untuk bermutasi nanti). Kemudian Anda berakhir dengan kode yang kurang dapat dibaca secara keseluruhan.

Tidak menyarankan bahwa Rust harus menjadi bahasa perbudakan & disiplin yang serius, tetapi dorongan lembut ke arah yang benar dapat dibenarkan secara moral, saya pikir (yaitu aturannya adalah "untuk kode yang aman, konstruksi yang lebih aman seharusnya tidak terlalu berisik daripada yang lebih kuat tetapi konstruksi yang lebih mudah dikacaukan").

Di satu sisi saya suka ini, karena itu akan menghilangkan ambiguitas visual dari formulir ini:

let mut x = 4,
    y = 8;  // is y mutable or not?

Tapi saya cenderung berpihak pada ssylvan. Mendeklarasikan yang bisa berubah tidak harus benar-benar _jelek_, ​​tapi saya pikir masuk akal jika mereka sedikit kurang nyaman untuk dibuat daripada yang tidak bisa diubah, jika hanya dengan satu penekanan tombol. Kata kunci pengaktif juga harus berbeda, dan (IMO) var terlalu banyak digunakan sebagai kata kunci deklarasi variabel generik untuk secara khusus menyampaikan mutabilitas dalam bahasa yang membanggakan kekekalan-oleh-default. Dan pikirkan programmer C# yang malang, untuk siapa var adalah let !

Saya masih menyukai ide untuk mengganti let mut dengan satu kata kunci, untuk mengatasi potongan kode di atas, tetapi apakah ada alasan untuk memperkenalkan kata kunci baru ketika mut itu sendiri sudah cukup, sesuai proposal asli di #1273?

@pcwalton menunjukkan masalah dengan hanya menggunakan mut : ada ambiguitas dengan record literal dan ekspresi blok yang membutuhkan lookahead sewenang-wenang untuk diselesaikan.

{ mut x: int ...

Rekam literal, atau blokir dengan variabel lokal?

Saya dapat melihat banyak programmer baru mengetahui bahwa var adalah cara Anda mendeklarasikan variabel di Rust, dan tidak menggunakan let sama sekali. Bagaimanapun, var adalah cara Anda mendeklarasikan variabel lokal dalam bahasa seperti JavaScript. Saya cenderung berpikir ini adalah hal yang baik tentang proposal ini.

Saya mendengar seseorang menunjukkan kemarin bahwa sekarang let dan var akan memiliki panjang yang sama, yang akan bagus untuk penyelarasan.

Saya agak acuh tak acuh, tetapi saya agak lebih suka var , karena lebih pendek. Membuat mutabilitas mengganggu bukanlah tujuan yang diinginkan seperti yang saya lihat. (Memang, saya cenderung berpikir peran bahasa pemrograman seharusnya tidak membuat sesuatu yang mengganggu — hanya _clear_, yang bukan hal yang sama.)

Meskipun saya masih waspada menggunakan let dan var bersama-sama (seperti Javascript, tetapi 100% berbeda), akan jauh lebih sedikit masalah jika ada lint pass untuk mendeteksi variabel yang dinyatakan dapat berubah tetapi tidak pernah benar-benar bermutasi.

Ada rencana untuk menjadikan mutabilitas sebagai bagian dari tipe. Apakah itu mempengaruhi penduduk setempat dan membuat ini tidak relevan?

Bagaimana tentang:

val x = ... // immutable (val-ue)
var y = ... // mutable (var-iable)

Seperti di Scala.

Saya pikir @brson benar dan masalah ini hilang setelah kami memindahkan mut ke dalam suatu tipe, yaitu Anda mendapatkan let x = mut 10;

Menutup masalah ini untuk saat ini; buka kembali jika Anda pikir saya salah!

Saya tidak yakin tentang ini. Saya suka gagasan untuk memindahkan mut ke dalam tipe, tetapi saya tidak tahu bahwa itu adalah "kesepakatan yang sudah selesai" --- mungkin ada keanehan yang tersisa di sana. Bagaimanapun, saya tidak pernah mempertimbangkan bahwa seseorang mungkin menulis let x = mut 5 , saya selalu berasumsi Anda akan menulis let mut x = 5 seperti hari ini; "kemampuan berubah-ubah" dari tipe variabel akan berasal dari cara variabel itu dideklarasikan, bukan nilai yang diberikan padanya.

Melakukan sebaliknya tampaknya menyiratkan bahwa jika Anda memiliki array x bertipe [mut int] dan Anda menulis let y = x[0] maka y dapat diubah? Atau sesuatu? Itu tampaknya tidak diinginkan.

@Dretch Saya tidak suka val/var karena mereka tidak cukup berbeda, meskipun preseden Scala bagus.

Saya berbagi keprihatinan @eholk tentang orang-orang yang belajar menggunakan var secara default. Cara kerjanya sekarang saya cenderung mendeklarasikan semuanya sebagai tidak dapat diubah, kemudian kompiler mengingatkan saya bahwa itu harus bisa berubah, lalu saya mengetik mut . Ini bisa dibilang perilaku yang baik yang tidak akan Anda lakukan dengan var/let split - mengetik var dan let sama-sama sulit tetapi Anda bahkan tidak dapat mengetik let mut tanpa mengetik let .

Tetapi saya tidak memiliki preferensi dan saya sangat menghargai ketika saya dapat menyusun fungsi-fungsi yang seluruhnya dari pernyataan-pernyataan yang dimulai dengan kata kunci tiga karakter.

@nikomatsakis Secara khusus, masuk akal bagi saya bahwa aturan tentang tugas tunggal harus berasal dari mutabilitas deklarasi daripada tipenya. Secara halus mengubah aturan penugasan berdasarkan jenisnya terasa lucu bagi saya.

Saya cenderung setuju dengan @pcwalton bahwa kita tidak boleh menghukum pemrogram menggunakan pengikatan yang bisa berubah jika itu yang mereka inginkan. Adapun kekhawatiran tentang orang-orang yang tidak perlu menggunakan var , kami dapat menambahkan peringatan opsional yang mengeluh jika pengikatan var ditetapkan secara tunggal. Tetapi saya juga berpikir bahwa kita dapat menetapkan preseden untuk gaya yang baik di rustc dan perpustakaan standar.

Dave

Apakah benar-benar mengerikan jika programmer mendeklarasikan semua variabel mereka bisa berubah? Sepertinya itu bukan akhir dari dunia jika kita memiliki satu set programmer Rust yang hanya berpikir var adalah bagaimana Anda mendeklarasikan variabel, dan set lain yang mengerti untuk menggunakan let sebagian besar waktu dan var bila diperlukan. Sebagai pemrogram Rust pertama, kita dapat mengatur preseden untuk menggunakan let dan var dengan benar.

IMHO desain sintaksis yang baik bukan hanya tentang membuat "segala sesuatu" yang mungkin ingin Anda lakukan nyaman, ini tentang mendorong orang dengan lembut ke "jalur mulus" dari semantik bahasa dan tujuan desain.

Misalnya, Anda mungkin tidak akan menambahkan dukungan sintaksis khusus untuk daftar tertaut di Rust (ala Haskell), karena salah satu prinsip dasar Rust adalah menjadi efisien, dan penggunaan daftar tertaut yang meluas akan bekerja bertentangan dengan prinsip itu. Untuk alasan yang sama, berbagi data yang dapat berubah di antara utas mungkin tidak terlalu nyaman (karena konkurensi yang aman adalah prinsip lain), juga tidak boleh sangat nyaman untuk melemparkan int sewenang-wenang ke pointer (karena keamanan memori adalah prinsip besar).

Bukan untuk mengatakan bahwa seharusnya tidak mungkin untuk melakukan hal-hal ini, pikiran, hanya secara proporsional merepotkan sehingga jelas dari sintaks yang merupakan cara idiomatik untuk menulis Rust.

Variabel yang dapat berubah (lokal) hampir tidak seburuk semua ini, tetapi jika Rust memang menyukai data yang tidak dapat diubah untuk alasan kebenaran dan pemeliharaan (sesuatu yang saya setujui secara pribadi), maka sintaks idealnya harus memberikan dorongan lembut ke arah itu. Bahkan satu karakter tambahan atau sigil pengubah tambahan atau apa pun akan cukup untuk memperjelas bahwa "biarkan" tidak terlalu rumit daripada "biarkan mut" atau "biarkan!" atau apa pun, dan karena itu harus menjadi default pilihan yang harus Anda coba ketika Anda sebenarnya tidak membutuhkan variabel untuk bisa berubah.

@ssylvan Oh, saya mengerti hal itu, ini hanya masalah derajat, dan keseimbangan pertukaran. Kami sudah mempromosikan kekekalan struktur data, dan lokal IMO yang tidak berubah kurang penting untuk dipromosikan daripada bidang yang tidak dapat diubah. (Terutama karena, IINM, kami tidak mengizinkan penduduk lokal yang dapat berubah untuk melarikan diri dalam penutupan tumpukan.) Dan hilangnya kemampuan untuk memfaktorkan ulang antara let dan var tanpa mengubah jumlah kolom melebihi manfaat dari mempromosikan penduduk setempat yang tidak berubah. Sulit untuk diukur, jadi saya rasa itu hanya perasaan saya.

Dave

Nah dalam hal ini setidaknya "let foo = mut bar" atau "let foo := bar" sebagai lawan dari "let mut foo = bar" akan membuat baris token pertama. Agaknya nama variabel akan memiliki panjang variabel sehingga tidak begitu penting untuk menghindari pengubah tambahan pada sisa pernyataan.

Oh hei, saya agak memihak pada ide := .

Dave

Setelah dipikir-pikir, Pascal secara permanen tidak keren. Saya ambil kembali. :)

Dave

Juga, let foo := bar mencegah sesuatu seperti ini:

let mut foo;
foo = bar;

Saya menemukan pola itu kadang-kadang berguna, meskipun sepertinya selalu ada cara lain untuk menulis pola yang sama.

@eholk Saya tidak berpikir itu mencegahnya. Tapi saya masih berpikir itu akan terlihat terlalu aneh untuk programmer dari hampir semua bahasa mainstream.

Dave

Mengenai := , Go menggunakannya untuk menunjukkan penetapan tipe-inferensial (meskipun itu belum menjadi bahasa utama). Tetapi saya dapat memperkirakan kesulitan membedakan antara dua bentuk secara sekilas:

let foo = "hello";
let foo := "hell";

argumen brson untuk sintaks saat ini (yaitu bahwa deklarasi yang dapat diubah terlebih dahulu memerlukan deklarasi yang tidak dapat diubah) meyakinkan. Ini benar-benar hebat jika bahasa pemrograman berpendirian, asalkan mereka tidak brengsek tentang hal itu. :)

Tidak tertarik pada = vs. := . Sebagian besar menentang val , var dan variasinya; itu sama sekali tidak _jelas_ bahwa ia mengontrol mutabilitas. Maksudku, aku tidak akan berhenti dengan jijik jika kita mengadopsi salah satunya, tapi kurasa "perlu menjelaskan mnemonic" adalah pertanda buruk. Saya lebih baik dengan:

  • Membiarkan tipe mendiktekannya.
  • Membiarkan mut saja bekerja sebagai deklarator lokal dan mengharuskan parser untuk menunda komitmen ke sintaks-rekaman vs. deklarasi lokal satu token tambahan; itu masih LL(1) hanya menambahkan status tata bahasa perantara ekstra, tidak ada backtracking tambahan (kedua cara maju valid).
  • Membiarkannya sebagai let mut .

Alasan utama untuk menghindari penduduk lokal yang berubah-ubah "tidak disengaja" adalah karena kami memperkenalkan penangkapan lingkungan, sehingga mereka berubah menjadi bentuk aksi jarak jauh, serta bahaya untuk berbagai analisis seperti meminjam.

(Semua let pada awalnya dapat diubah, tetapi kami juga tidak memiliki tangkapan lingkungan, hanya mengikat. Sekarang kami tidak memiliki ikatan, hanya tangkapan env. Tomayto, tomahto.)

Saya percaya mutables tidak dapat ditangkap secara implisit sekarang.

@graydon benar bahwa ada dua motivasi asli. Namun hanya satu yang masih relevan. Dua motivasi itu adalah

  • penangkapan "by-copy" implisit dari variabel yang bisa berubah dalam fn@
  • memahami data apa yang bisa berubah dan apa yang tidak untuk dipinjam

Ternyata yang terakhir sudah tidak relevan lagi. Penggunaan variabel yang dapat berubah/tidak dapat diubah terlalu kasar dalam praktiknya sehingga borrowck memiliki ide untuk meminjam variabel "sementara" --- variabel yang dapat berubah dapat dipinjam dengan ptr yang tidak dapat diubah selama variabel tersebut tidak dimodifikasi saat pointer berada di cakupan.

Kita mungkin bisa menghapus ide tentang penduduk lokal yang bisa berubah/tidak berubah dan kembali ke aturan lama --- semuanya bisa berubah. Kami kemudian dapat mengeluarkan peringatan ketika variabel yang secara implisit disalin ke dalam penutupan dimodifikasi setelah penutupan dibuat.

Ada motivasi ketiga: variabel yang tidak dapat diubah lebih mudah untuk dipikirkan. Jika semuanya bisa berubah, Anda harus memindai seluruh fungsi untuk melihat nilai apa yang mungkin dimiliki variabel selama masa pakainya. Setiap variabel berpotensi memiliki aliran data yang rumit (terutama dengan loop, cabang, parameter fungsi yang dapat diubah, dll.) dan sulit untuk melihat apa yang terjadi tanpa menganalisis setiap pernyataan dengan cermat. Jika Anda hanya memiliki satu atau dua mutable dalam suatu fungsi, itu semacam tindakan untuk "menandai" mereka sehingga Anda lebih berhati-hati saat membaca kode yang melibatkan hem.

@Dretch Saya juga suka gaya Scala, dengan kata kunci "val" dan "var".

Saya suka bagaimana sintaks saat ini menyebabkan mutable menonjol seperti jempol yang sakit; itu membuat pemindaian kode lebih mudah. val dan var tampak terlalu mirip secara visual dalam hal itu. Yang tidak berarti bahwa yang bisa berubah benar-benar _harus_ menonjol, tetapi menjaga kata kunci berbeda secara visual adalah aspek penting dari kegunaan.

Saya mengerti bahwa bidang yang bisa berubah akan dihapus dari karat. Apakah itu berarti mut kemudian dapat digunakan sebagai ganti let mut karena ambiguitas record/variable-in-block akan hilang?

Saya juga percaya catatan struktural sedang berjalan, yang menghilangkan ambiguitas bahkan jika bidang yang bisa berubah tetap ada.

@Dretch memang benar bahwa bidang yang bisa berubah sedang dalam perjalanan keluar, dan catatan struktural sudah hilang.

Saya sebagian besar tidak peduli dengan masalah ini, meskipun saya ingin menunjukkan bahwa _mungkin_ masuk akal untuk mut menjadi kata kunci deklarasi dalam dirinya sendiri (seperti yang diusulkan Dretch), dalam kasus pembekuan/pencairan . Bandingkan hari ini:

let foo = 1;  // immutable
/* 10,000 lines of code here */
let mut foo = foo;  // we're making foo mutable, totally understandable
/* 10,000 lines of code here */
let foo = foo;  // potential wtf

Dengan usulan:

let foo = 1;  // immutable
/* 10,000 lines of code here */
mut foo = foo;  // a mutable foo, no problems here
/* 10,000 lines of code here */
let foo = foo;  // slightly less of a potential for wtf, since we officially have two declaration forms

Meskipun saya juga merasa ini akan membuat Rust-isme "tidak adanya mut menyiratkan kekekalan" kurang konsisten, karena kami masih akan menulis let foo = 1; daripada hanya foo = 1; (bentuk terakhir jelas tidak diinginkan untuk deklarasi).

Kotlin juga menggunakan val dan var .

Saya tidak berpikir kita akan membuat perubahan ini, tetapi saya akan mencalonkan untuk pencapaian 1, yang didefinisikan dengan baik, sehingga kita dapat menyelesaikannya.

konsensus adalah untuk tidak melakukan ini, karena tidak sesuai dengan memindahkan mut ke pola binding. penutupan.

Apakah halaman ini membantu?
0 / 5 - 0 peringkat