Apa manfaat dari memiliki operator penugasan mengembalikan nilai?

27

Saya sedang mengembangkan bahasa yang ingin saya ganti Javascript dan PHP. (Saya tidak dapat melihat masalah dengan ini. Ini tidak seperti salah satu dari bahasa ini memiliki basis instalasi yang besar.)

Salah satu hal yang ingin saya ubah adalah mengubah operator penugasan menjadi perintah penugasan, menghilangkan kemampuan untuk menggunakan nilai yang dikembalikan.

x=1;          /* Assignment. */
if (x==1) {}  /* Comparison. */
x==1;         /* Error or warning, I've not decided yet. */
if (x=1) {}   /* Error. */

Saya tahu ini berarti bahwa fungsi satu baris yang sangat disukai orang C tidak akan berfungsi lagi. Saya pikir (dengan sedikit bukti di luar pengalaman pribadi saya) bahwa sebagian besar kali ini terjadi, itu benar-benar dimaksudkan untuk operasi perbandingan.

Atau itu? Apakah ada kegunaan praktis dari nilai pengembalian operator penugasan yang tidak dapat ditulis ulang secara sepele? (Untuk bahasa apa pun yang memiliki konsep seperti itu.)

billpg
sumber
12
JS dan PHP tidak memiliki "install base" yang besar?
mhr
47
@mri saya curiga sarkasme.
Andy Hunt
12
Satu-satunya kasus berguna yang bisa saya ingat adalah while((x = getValue()) != null) {}. Penggantian akan lebih buruk karena Anda harus menggunakan breakatau mengulang x = getValuetugas.
CodesInChaos
12
@moh Ooh tidak, saya mendengar kedua bahasa itu hanya hal-hal sepele tanpa investasi yang berarti sama sekali. Begitu beberapa orang yang bersikeras menggunakan JS melihat bahasa saya, mereka akan beralih ke bahasa saya dan tidak perlu menulis === lagi. Saya sama yakin pembuat browser akan segera meluncurkan pembaruan yang mencakup bahasa saya bersama JS. :)
billpg
4
Saya menyarankan kepada Anda bahwa jika niat Anda adalah untuk meningkatkan bahasa yang ada dan Anda bermaksud untuk diadopsi secara luas, maka kompatibilitas mundur 100% dengan bahasa yang ada adalah baik. Lihat TypeScript sebagai contoh. Jika niat Anda adalah untuk memberikan alternatif yang lebih baik daripada bahasa yang ada maka Anda memiliki masalah yang jauh lebih sulit. Bahasa baru harus menyelesaikan masalah realistis yang ada jauh lebih baik daripada bahasa yang ada untuk membayar biaya pengalihan. Belajar bahasa adalah investasi dan perlu terbayar.
Eric Lippert

Jawaban:

25

Secara teknis, beberapa gula sintaksis layak untuk disimpan bahkan jika dapat diganti secara sepele, jika meningkatkan keterbacaan beberapa operasi umum. Tapi penugasan-sebagai-ekspresi tidak termasuk di bawah itu. Bahaya mengetik di tempat perbandingan berarti itu jarang digunakan (kadang-kadang bahkan dilarang oleh panduan gaya) dan memicu pengambilan ganda setiap kali digunakan. Dengan kata lain, manfaat keterbacaan kecil dalam jumlah dan besarnya.

Melihat bahasa yang ada yang melakukan ini mungkin bermanfaat.

  • Java dan C # menyimpan penugasan ekspresi tetapi menghapus perangkap yang Anda sebutkan dengan meminta persyaratan untuk mengevaluasi ke booleans. Ini sebagian besar tampaknya bekerja dengan baik, meskipun orang kadang-kadang mengeluh bahwa ini melarang kondisi seperti if (x)di tempat if (x != null)atau if (x != 0)tergantung pada jenis x.
  • Python menjadikan penugasan sebagai pernyataan yang tepat alih-alih ekspresi. Proposal untuk mengubah ini kadang-kadang mencapai milis python-ideas, tetapi kesan subjektif saya adalah bahwa ini lebih jarang terjadi dan menghasilkan lebih sedikit noise setiap kali dibandingkan dengan fitur "hilang" lainnya seperti loop do-while, pergantian pernyataan, lambda multi-line, dll.

Namun, Python memungkinkan satu kasus khusus, menugaskan ke beberapa nama sekaligus: a = b = c. Ini dianggap sebagai pernyataan yang setara dengan b = c; a = b, dan kadang-kadang digunakan, jadi mungkin perlu ditambahkan ke bahasa Anda juga (tapi saya tidak akan berkeringat, karena penambahan ini harus kompatibel dengan mundur).


sumber
5
+1 untuk memunculkan a = b = cyang jawaban lainnya tidak benar-benar muncul.
Leo
6
Resolusi ketiga adalah menggunakan simbol yang berbeda untuk penugasan. Penggunaan Pascal :=untuk penugasan.
Brian
5
@ Brian: Memang, seperti halnya C #. =adalah penugasan, ==adalah perbandingan.
Marjan Venema
3
Di C #, sesuatu seperti if (a = true)akan melempar peringatan C4706 ( The test value in a conditional expression was the result of an assignment.). GCC dengan C juga akan melempar a warning: suggest parentheses around assignment used as truth value [-Wparentheses]. Peringatan-peringatan itu dapat dibungkam dengan seperangkat tanda kurung tambahan, tetapi peringatan itu ada untuk mendorong secara eksplisit menunjukkan bahwa tugas itu disengaja.
Bob
2
@delnan Hanya komentar yang agak umum, tetapi dipicu oleh "hapus jebakan yang Anda sebutkan dengan meminta persyaratan untuk mengevaluasi ke booleans" - a = true tidak mengevaluasi ke Boolean dan karenanya bukan kesalahan, tetapi juga menimbulkan peringatan terkait di C #.
Bob
11

Apakah ada kegunaan praktis dari nilai pengembalian operator penugasan yang tidak dapat ditulis ulang secara sepele?

Secara umum, tidak. Gagasan memiliki nilai ekspresi penugasan menjadi nilai yang diberikan berarti bahwa kita memiliki ekspresi yang dapat digunakan untuk efek samping dan nilainya , dan yang dianggap oleh banyak orang membingungkan.

Penggunaan umum biasanya untuk membuat ekspresi kompak:

x = y = z;

memiliki semantik dalam C # dari "convert z ke tipe y, tetapkan nilai yang dikonversi ke y, nilai yang dikonversi adalah nilai dari ekspresi, konversikan ke tipe x, tetapkan ke x".

Tetapi kita sudah berada di bidang efek samping yang tidak disengaja dalam konteks pernyataan, jadi benar-benar ada sedikit manfaat yang menarik untuk itu selama

y = z;
x = y;

Begitu pula dengan

M(x = 123);

menjadi singkatan untuk

x = 123;
M(x);

Sekali lagi, dalam kode asli kita menggunakan ekspresi baik untuk efek samping dan nilainya, dan kami membuat pernyataan yang memiliki dua efek samping, bukan satu. Keduanya bau; cobalah untuk memiliki satu efek samping per pernyataan, dan gunakan ekspresi untuk nilainya, bukan untuk efek sampingnya.

Saya sedang mengembangkan bahasa yang ingin saya ganti Javascript dan PHP.

Jika Anda benar-benar ingin berani dan menekankan bahwa penugasan adalah pernyataan dan bukan persamaan, maka saran saya adalah: buatlah dengan jelas pernyataan penugasan .

let x be 1;

Yang merah. Atau

x <-- 1;

atau bahkan lebih baik:

1 --> x;

Atau bahkan lebih baik lagi

1 → x;

Sama sekali tidak mungkin salah satu dari mereka akan bingung x == 1.

Eric Lippert
sumber
1
Apakah dunia siap untuk simbol Unicode non-ASCII dalam bahasa pemrograman?
billpg
Seperti halnya saya akan menyukai apa yang Anda sarankan, salah satu tujuan saya adalah bahwa sebagian besar JavaScript yang "ditulis dengan baik" dapat diangkut dengan sedikit atau tanpa modifikasi.
billpg
2
@ billpg: Apakah dunia sudah siap ? Saya tidak tahu - apakah dunia siap untuk APL pada tahun 1964, berpuluh-puluh tahun sebelum penemuan Unicode? Berikut adalah program di APL yang memilih permutasi acak dari enam angka dari 40 yang pertama: x[⍋x←6?40] APL membutuhkan keyboard khusus sendiri, tetapi itu adalah bahasa yang cukup sukses.
Eric Lippert
@ billpg: Workshop Macintosh Programmer menggunakan simbol non-ASCII untuk hal-hal seperti tag regex atau pengalihan stderr. Di sisi lain, MPW memiliki keuntungan bahwa Macintosh membuatnya mudah untuk mengetik karakter non-ASCII. Saya harus mengakui beberapa kebingungan mengapa driver keyboard AS tidak memberikan cara yang layak untuk mengetik karakter non-ASCII. Entri Alt-number tidak hanya membutuhkan pencarian kode karakter - di banyak aplikasi bahkan tidak berfungsi.
supercat
Hm, mengapa orang lebih suka menetapkan "ke kanan" seperti a+b*c --> x? Ini terlihat aneh bagiku.
Ruslan
9

Banyak bahasa yang memilih rute untuk membuat penugasan sebuah pernyataan daripada ekspresi, termasuk Python:

foo = 42 # works
if foo = 42: print "hi" # dies
bar(foo = 42) # keyword arg

dan Golang:

var foo int
foo = 42 # works
if foo = 42 { fmt.Printn("hi") } # dies

Bahasa-bahasa lain tidak memiliki tugas, tetapi binding cakupan, misalnya OCaml:

let foo = 42 in
  if foo = 42 then
    print_string "hi"

Namun, itu letadalah ekspresi itu sendiri.

Keuntungan dari mengizinkan penugasan adalah bahwa kita dapat secara langsung memeriksa nilai pengembalian suatu fungsi di dalam kondisional, misalnya dalam cuplikan Perl ini:

if (my $result = some_computation()) {
  say "We succeeded, and the result is $result";
}
else {
  warn "Failed with $result";
}

Perl juga menambahkan deklarasi ke kondisi itu saja, yang membuatnya sangat berguna. Ini juga akan memperingatkan jika Anda menetapkan di dalam kondisi tanpa menyatakan variabel baru di sana - if ($foo = $bar)akan memperingatkan, if (my $foo = $bar)tidak akan.

Membuat penugasan dalam pernyataan lain biasanya cukup, tetapi dapat membawa masalah pelingkupan

my $result = some_computation()
if ($result) {
  say "We succeeded, and the result is $result";
}
else {
  warn "Failed with $result";
}
# $result is still visible here - eek!

Golang sangat bergantung pada nilai kembali untuk pengecekan kesalahan. Oleh karena itu memungkinkan persyaratan mengambil pernyataan inisialisasi:

if result, err := some_computation(); err != nil {
  fmt.Printf("Failed with %d", result)
}
fmt.Printf("We succeeded, and the result is %d\n", result)

Bahasa lain menggunakan sistem tipe untuk melarang ekspresi non-boolean di dalam sebuah kondisi:

int foo;
if (foo = bar()) // Java does not like this

Tentu saja itu gagal ketika menggunakan fungsi yang mengembalikan boolean.

Kami sekarang telah melihat mekanisme yang berbeda untuk bertahan terhadap penugasan yang tidak disengaja:

  • Larang penugasan sebagai ungkapan
  • Gunakan pengecekan tipe statis
  • Tugas tidak ada, kami hanya memiliki letikatan
  • Izinkan pernyataan inisialisasi, abaikan penugasan sebaliknya
  • Larang penugasan di dalam kondisi tanpa deklarasi

Saya telah memeringkatnya dalam urutan preferensi naik - tugas dalam ekspresi dapat berguna (dan mudah untuk menghindari masalah Python dengan memiliki sintaks deklarasi eksplisit, dan sintaks argumen bernama berbeda). Tapi tidak masalah untuk melarang mereka, karena ada banyak opsi lain untuk efek yang sama.

Kode bebas bug lebih penting daripada kode singkat.

amon
sumber
+1 untuk "Larang penugasan sebagai ungkapan". Kasus penggunaan untuk penugasan-sebagai-an-ekspresi tidak membenarkan potensi bug dan masalah keterbacaan.
aduk
7

Anda berkata, "Saya pikir (dengan sedikit bukti di luar pengalaman pribadi saya) bahwa sebagian besar dari ini terjadi, itu benar-benar dimaksudkan untuk operasi perbandingan."

Mengapa tidak MEMPERBAIKI MASALAH?

Alih-alih = untuk penugasan dan == untuk uji kesetaraan, mengapa tidak menggunakan: = untuk penugasan dan = (atau bahkan ==) untuk kesetaraan?

Mengamati:

if (a=foo(bar)) {}  // obviously equality
if (a := foo(bar)) { do something with a } // obviously assignment

Jika Anda ingin mempersulit programmer untuk keliru dalam menentukan tugas untuk kesetaraan, maka buatlah lebih sulit.

Pada saat yang sama, jika Anda BENAR-BENAR ingin memperbaiki masalah, Anda akan menghapus crock yang mengklaim boolean hanya bilangan bulat dengan nama gula simbolis yang telah ditentukan. Jadikan mereka tipe yang berbeda sama sekali. Lalu, bukannya mengatakan

int a = some_value();
if (a) {}

Anda memaksa programmer untuk menulis:

int a = some_value();
if (a /= 0) {} // Note that /= means 'not equal'.  This is your Ada lesson for today.

Faktanya adalah penugasan sebagai operator merupakan konstruk yang sangat berguna. Kami tidak menghilangkan pisau cukur karena beberapa orang memotong sendiri. Sebaliknya, Raja Gillette menemukan pisau cukur.

John R. Strohm
sumber
2
(1) :=untuk penugasan dan =untuk kesetaraan mungkin memperbaiki masalah ini, tetapi dengan biaya mengasingkan setiap programmer yang tidak tumbuh menggunakan set kecil bahasa non-mainstream. (2) Jenis selain bool yang memungkinkan dalam kondisi tidak selalu karena mencampur bool dan bilangan bulat, itu cukup untuk memberikan interpretasi yang benar / salah untuk jenis lainnya. Bahasa yang lebih baru yang tidak takut untuk menyimpang dari C telah melakukannya untuk banyak jenis selain bilangan bulat (misalnya Python menganggap koleksi kosong salah).
1
Dan mengenai pisau cukur: Yang melayani kasus penggunaan yang membutuhkan ketajaman. Di sisi lain, saya tidak yakin pemrograman dengan baik memerlukan penugasan ke variabel di tengah evaluasi ekspresi. Jika ada cara sederhana, berteknologi rendah, aman dan hemat biaya untuk membuat rambut tubuh menghilang tanpa ujung yang tajam, saya yakin pisau cukur akan dipindahkan atau setidaknya dibuat jauh lebih langka.
1
@delnan: Orang bijak pernah berkata, "Jadikan sesederhana mungkin, tetapi tidak sederhana." Jika tujuan Anda adalah untuk menghilangkan sebagian besar kesalahan a = b vs a == b, membatasi domain tes bersyarat ke booleans dan menghilangkan aturan konversi tipe default untuk <other> -> boolean memberi Anda hampir semua cara sana. Pada titik itu, jika (a = b) {} hanya sah secara hukum jika a dan b keduanya boolean dan a adalah nilai hukum.
John R. Strohm
Membuat penugasan sebuah pernyataan setidaknya sesederhana - dibilang lebih sederhana daripada - perubahan yang Anda usulkan, dan mencapai setidaknya sebanyak - bahkan lebih banyak (bahkan tidak mengizinkan if (a = b)untuk menilai nilai a, boolean a, b). Dalam bahasa tanpa mengetik statis, ini juga memberikan pesan kesalahan yang jauh lebih baik (pada waktu parse vs waktu berjalan). Selain itu, mencegah "a = b vs a == b kesalahan" mungkin bukan satu-satunya tujuan yang relevan. Sebagai contoh, saya juga ingin mengizinkan kode ingin if items:berarti if len(items) != 0, dan bahwa saya harus menyerah untuk membatasi persyaratan untuk boolean.
1
@delnan Pascal adalah bahasa non-mainstream? Jutaan orang belajar pemrograman menggunakan Pascal (dan / atau Modula, yang berasal dari Pascal). Dan Delphi masih umum digunakan di banyak negara (mungkin tidak begitu banyak di negara Anda).
jwenting
5

Untuk benar-benar menjawab pertanyaan, ya ada banyak kegunaan ini meskipun mereka sedikit niche.

Misalnya di Jawa:

while ((Object ob = x.next()) != null) {
    // This will loop through calling next() until it returns null
    // The value of the returned object is available as ob within the loop
}

Alternatif tanpa menggunakan tugas yang disematkan memerlukan yang obditentukan di luar lingkup loop dan dua lokasi kode terpisah yang memanggil x.next ().

Sudah disebutkan bahwa Anda dapat menetapkan beberapa variabel dalam satu langkah.

x = y = z = 3;

Hal semacam ini adalah penggunaan yang paling umum, tetapi programmer kreatif akan selalu menghasilkan lebih banyak.

Tim B
sumber
Apakah itu sementara kondisi loop deallocate dan membuat obobjek baru dengan setiap loop?
user3932000
@ user3932000 Dalam hal itu mungkin tidak, biasanya x.next () mengulangi sesuatu. Sangat mungkin bahwa itu bisa terjadi.
Tim B
1

Karena Anda bisa membuat semua aturan, mengapa sekarang memungkinkan penugasan untuk mengubah nilai, dan tidak memungkinkan penugasan di dalam langkah-langkah bersyarat? Ini memberi Anda gula sintaksis untuk memudahkan inisialisasi, sambil tetap mencegah kesalahan pengkodean yang umum.

Dengan kata lain, buat ini legal:

a=b=c=0;

Tetapi jadikan ini ilegal:

if (a=b) ...
Bryan Oakley
sumber
2
Itu sepertinya aturan yang agak ad-hoc. Membuat penugasan pernyataan dan memperluasnya untuk memungkinkan a = b = ctampaknya lebih ortogonal, dan lebih mudah untuk diterapkan juga. Kedua pendekatan ini tidak setuju tentang penugasan dalam ekspresi ( a + (b = c)), tetapi Anda belum memihak mereka, jadi saya menganggap mereka tidak masalah.
"mudah diimplementasikan" seharusnya tidak menjadi pertimbangan. Anda mendefinisikan antarmuka pengguna - mengutamakan kebutuhan pengguna. Anda hanya perlu bertanya pada diri sendiri apakah perilaku ini membantu atau menghambat pengguna.
Bryan Oakley
jika Anda melarang konversi implisit ke bool maka Anda tidak perlu khawatir tentang penugasan dalam kondisi
ratchet freak
Lebih mudah diterapkan adalah salah satu argumen saya. Bagaimana dengan yang lainnya? Dari sudut UI, saya dapat menambahkan bahwa desain IMHO tidak koheren dan pengecualian ad-hoc umumnya menghalangi pengguna dalam grokking dan menginternalisasi aturan.
@ scratchetfreak Anda masih dapat mengalami masalah dengan menetapkan bools aktual
jk.
0

Dengan suara itu, Anda berada di jalur untuk menciptakan bahasa yang cukup ketat.

Dengan pemikiran itu, memaksa orang untuk menulis:

a=c;
b=c;

dari pada:

a=b=c;

mungkin tampak peningkatan untuk mencegah orang melakukan:

if (a=b) {

ketika mereka bermaksud melakukan:

if (a==b) {

tetapi pada akhirnya, kesalahan semacam ini mudah dideteksi dan diperingatkan apakah itu kode hukum atau tidak.

Namun, ada beberapa situasi di mana melakukan:

a=c;
b=c;

bukan berarti itu

if (a==b) {

akan benar.

Jika c sebenarnya adalah fungsi c () maka itu bisa mengembalikan hasil yang berbeda setiap kali dipanggil. (mungkin juga mahal secara komputasi ...)

Demikian juga jika c adalah pointer ke perangkat keras yang dipetakan memori, maka

a=*c;
b=*c;

keduanya mungkin berbeda, dan juga mungkin memiliki efek elektronik pada perangkat keras pada setiap pembacaan.

Ada banyak permutasi lain dengan perangkat keras di mana Anda harus tepat tentang alamat memori yang dibaca, ditulis ke dan di bawah batasan waktu tertentu, di mana melakukan banyak tugas pada baris yang sama cepat, sederhana dan jelas, tanpa risiko waktu yang variabel sementara diperkenalkan

Michael Shaw
sumber
4
Setara dengan a = b = cbukan a = c; b = c, itu b = c; a = b. Ini menghindari duplikasi efek samping dan juga menjaga modifikasi adan bdalam urutan yang sama. Juga, semua argumen yang terkait dengan perangkat keras ini agak bodoh: Kebanyakan bahasa bukan bahasa sistem dan tidak dirancang untuk menyelesaikan masalah ini atau digunakan dalam situasi di mana masalah ini terjadi. Ini berlaku dua kali lipat untuk bahasa yang mencoba menggeser JavaScript dan / atau PHP.
delnan, masalahnya bukan ini contoh yang dibuat-buat, mereka. Intinya masih berdiri bahwa mereka menunjukkan jenis tempat di mana menulis a = b = c adalah umum, dan dalam kasus perangkat keras, dianggap praktik yang baik, seperti yang diminta OP. Saya yakin mereka akan dapat mempertimbangkan relevansi mereka dengan lingkungan yang diharapkan
Michael Shaw
Menengok ke belakang, masalah saya dengan jawaban ini bukan terutama karena berfokus pada kasus penggunaan pemrograman sistem (meskipun itu akan cukup buruk, cara itu ditulis), tetapi bahwa ia bertumpu pada asumsi penulisan ulang yang salah. Contoh-contoh itu bukan contoh tempat-tempat a=b=cyang umum / berguna, mereka adalah contoh tempat di mana urutan dan jumlah efek samping harus dijaga. Itu sepenuhnya independen. Tulis ulang tugas yang dirantai dengan benar dan kedua varian sama-sama benar.
@delnan: Nilai tersebut dikonversi ke jenis bdalam satu temp, dan yang dikonversi ke jenis adalam temp lainnya. Waktu relatif kapan nilai-nilai itu sebenarnya disimpan tidak ditentukan. Dari perspektif desain bahasa, saya pikir masuk akal untuk mengharuskan semua nilai dalam pernyataan penugasan berganda memiliki tipe yang cocok, dan mungkin juga mengharuskan agar tidak ada satupun yang volatile.
supercat
0

Manfaat terbesar bagi pikiran saya memiliki penugasan menjadi ekspresi adalah bahwa hal itu memungkinkan tata bahasa Anda menjadi lebih sederhana jika salah satu tujuan Anda adalah bahwa "semuanya adalah ekspresi" - tujuan LISP pada khususnya.

Python tidak memiliki ini; memiliki ekspresi dan pernyataan, tugas menjadi pernyataan. Tetapi karena Python mendefinisikan lambdaformulir sebagai ekspresi parameter tunggal , itu berarti Anda tidak dapat menetapkan variabel di dalam lambda. Ini kadang-kadang merepotkan, tetapi bukan masalah kritis, dan ini tentang satu-satunya downside dalam pengalaman saya untuk memiliki penugasan menjadi pernyataan dengan Python.

Salah satu cara untuk memungkinkan penugasan, atau lebih tepatnya efek penugasan, untuk menjadi ekspresi tanpa memperkenalkan potensi if(x=1)kecelakaan yang C miliki adalah dengan menggunakan letkonstruk seperti LISP , seperti (let ((x 2) (y 3)) (+ x y))yang mungkin dalam bahasa Anda dievaluasi sebagai 5. Menggunakan letcara ini tidak perlu secara teknis sama sekali dalam bahasa Anda, jika Anda mendefinisikan letsebagai menciptakan ruang lingkup leksikal. Didefinisikan seperti itu, letkonstruk dapat dikompilasi dengan cara yang sama seperti membangun dan memanggil fungsi penutupan bersarang dengan argumen.

Di sisi lain, jika Anda hanya peduli dengan if(x=1)kasus ini, tetapi ingin penugasan menjadi ekspresi seperti dalam C, mungkin hanya memilih token yang berbeda sudah cukup. Penugasan: x := 1atau x <- 1. Perbandingan: x == 1. Kesalahan sintaks: x = 1.

wberry
sumber
1
letberbeda dari penugasan dalam lebih banyak cara daripada secara teknis memperkenalkan variabel baru dalam lingkup baru. Sebagai permulaan, itu tidak berpengaruh pada kode di luar lettubuh, dan karena itu memerlukan bersarang semua kode (apa yang harus menggunakan variabel) lebih lanjut, penurunan signifikan dalam kode tugas-berat. Jika seseorang turun rute itu, set!akan menjadi analog Lisp yang lebih baik - sama sekali tidak seperti perbandingan, namun tidak memerlukan bersarang atau ruang lingkup baru.
@delnan: Saya ingin melihat kombinasi sintaks deklarasi-dan-tetapkan yang akan melarang penugasan kembali tetapi akan mengizinkan deklarasi ulang, tunduk pada aturan bahwa (1) deklarasi ulang hanya akan sah untuk pengidentifikasi deklarasi-dan-tetapkan, dan (2) ) deklarasi ulang akan "tidak mendeklarasikan" variabel dalam semua cakupan yang melampirkan. Dengan demikian, nilai dari setiap pengidentifikasi yang valid akan menjadi apa pun yang diberikan dalam deklarasi nama itu sebelumnya. Itu akan tampak sedikit lebih bagus daripada harus menambahkan blok pelingkupan untuk variabel yang hanya digunakan untuk beberapa baris, atau harus merumuskan nama baru untuk setiap variabel temp.
supercat
0

Saya tahu ini berarti bahwa fungsi satu baris yang sangat disukai orang C tidak akan berfungsi lagi. Saya pikir (dengan sedikit bukti di luar pengalaman pribadi saya) bahwa sebagian besar kali ini terjadi, itu benar-benar dimaksudkan untuk operasi perbandingan.

Memang. Ini bukan hal yang baru, semua himpunan bagian yang aman dari bahasa C telah membuat kesimpulan ini.

MISRA-C, CERT-C dan seterusnya semua larangan dalam kondisi, hanya karena berbahaya.

Tidak ada kasus di mana kode bergantung pada penugasan dalam kondisi tidak dapat ditulis ulang.


Selain itu, standar tersebut juga memperingatkan terhadap penulisan kode yang bergantung pada urutan evaluasi. Penugasan berganda pada satu baris tunggal x=y=z;merupakan kasus demikian. Jika sebuah baris dengan banyak penugasan berisi efek samping (fungsi panggilan, mengakses variabel volatil, dll.), Anda tidak dapat mengetahui efek samping mana yang akan terjadi terlebih dahulu.

Tidak ada titik urutan antara evaluasi operan. Jadi kita tidak bisa tahu apakah subekspresi yakan dievaluasi sebelum atau sesudah z: itu adalah perilaku yang tidak ditentukan dalam C. Dengan demikian kode tersebut berpotensi tidak dapat diandalkan, tidak portabel dan tidak sesuai dengan subset aman yang disebutkan dalam C.

Solusinya adalah mengganti kode dengan y=z; x=y;. Ini menambahkan titik urutan dan menjamin urutan evaluasi.


Jadi berdasarkan pada semua masalah yang disebabkan oleh C ini, bahasa modern apa pun akan baik untuk kedua penugasan tugas di dalam kondisi, serta beberapa penugasan pada satu baris tunggal.


sumber