Mengapa pintasan seperti x + = y dianggap praktik yang baik?

305

Saya tidak tahu apa sebutannya ini, tetapi saya selalu melihatnya. Implementasi Python adalah sesuatu seperti:

x += 5sebagai notasi steno untuk x = x + 5.

Tetapi mengapa ini dianggap praktik yang baik? Saya telah menjalankannya di hampir setiap buku atau tutorial pemrograman yang pernah saya baca untuk Python, C, R , dan sebagainya. Saya merasa nyaman, menghemat tiga kali penekanan tombol termasuk spasi. Tetapi mereka selalu membuat saya tersandung ketika saya membaca kode, dan setidaknya dalam pikiran saya, membuatnya kurang mudah dibaca, tidak lebih.

Apakah saya kehilangan alasan yang jelas dan jelas mengapa ini digunakan di semua tempat?

Fomite
sumber
@ EricLippert: Apakah C # menangani ini dengan cara yang sama seperti jawaban teratas dijelaskan? Apakah ini sebenarnya lebih efisien untuk dikatakan x += 5dari CLR x = x + 5? Atau itu benar-benar hanya gula sintaksis seperti yang Anda sarankan?
blesh
24
@blesh: Detail kecil tentang bagaimana seseorang mengekspresikan penambahan dalam kode sumber berdampak pada efisiensi kode yang dapat dieksekusi yang mungkin terjadi pada tahun 1970; sudah pasti bukan sekarang. Mengoptimalkan kompiler itu baik, dan Anda memiliki kekhawatiran lebih besar daripada nanosecond di sana-sini. Gagasan bahwa operator + = dikembangkan "dua puluh tahun yang lalu" jelas salah; almarhum Dennis Richie mengembangkan C dari tahun 1969 hingga 1973 di Bell Labs.
Eric Lippert
1
Lihat blogs.msdn.com/b/ericlippert/archive/2011/03/29/… (lihat juga bagian dua)
SLaks
5
Kebanyakan programmer fungsional akan menganggap praktik buruk ini.
Pete Kirkham

Jawaban:

598

Itu bukan steno.

The +=simbol muncul dalam bahasa C pada 1970-an, dan - dengan C gagasan "assembler pintar" sesuai dengan mode instruksi mesin dan adressing jelas berbeda:

Hal-hal seperti " i=i+1", "i+=1"dan" ++i", meskipun pada level abstrak menghasilkan efek yang sama, berhubungan pada level rendah dengan cara kerja prosesor yang berbeda.

Secara khusus ketiga ekspresi tersebut, dengan asumsi ivariabel berada di alamat memori yang disimpan dalam register CPU (sebut saja D- anggap sebagai "penunjuk ke int") dan ALU prosesor mengambil parameter dan mengembalikan hasil dalam "Akumulator" (sebut saja A - pikirkan sebagai int).

Dengan kendala-kendala ini (sangat umum di semua mikroprosesor dari periode itu), kemungkinan besar terjemahannya

;i = i+1;
MOV A,(D); //Move in A the content of the memory whose address is in D
ADD A, 1;  //The addition of an inlined constant
MOV (D) A; //Move the result back to i (this is the '=' of the expression)

;i+=1;
ADD (D),1; //Add an inlined constant to a memory address stored value

;++i;
INC (D); //Just "tick" a memory located counter

Cara pertama untuk melakukannya adalah disoptimal, tetapi lebih umum ketika beroperasi dengan variabel daripada konstan ( ADD A, Batau ADD A, (D+x)) atau ketika menerjemahkan ekspresi yang lebih kompleks (mereka semua mendidih dalam mendorong operasi prioritas rendah dalam tumpukan, sebut prioritas tinggi, pop dan ulangi sampai semua argumen dihilangkan).

Yang kedua lebih khas dari "mesin negara": kita tidak lagi "mengevaluasi ekspresi", tetapi "mengoperasikan nilai": kita masih menggunakan ALU, tetapi menghindari memindahkan nilai sekitar karena hasilnya diperbolehkan untuk mengganti parameter. Instruksi semacam ini tidak dapat digunakan di mana ekspresi yang lebih rumit diperlukan: i = 3*i + i-2tidak dapat dioperasikan di tempat, karena idiperlukan lebih banyak kali.

Yang ketiga sederhana bahkan tidak mempertimbangkan gagasan "penambahan", tetapi menggunakan sirkuit yang lebih "primitif" (dalam arti komputasi) untuk penghitung. Instruksi ini disingkat, memuat lebih cepat dan dieksekusi segera, karena jaringan kombinatorial diperlukan untuk retrofit register untuk menjadikannya penghitung yang lebih kecil, dan karenanya lebih cepat daripada yang dari penambah penuh.

Dengan kompiler kontemporer (lihat C, sekarang), memungkinkan optimisasi kompiler, korespondensi dapat ditukar berdasarkan kenyamanan, tetapi masih ada perbedaan konseptual dalam semantik.

x += 5 cara

  • Temukan tempat yang diidentifikasi oleh x
  • Tambahkan 5 ke dalamnya

Tetapi x = x + 5berarti:

  • Evaluasi x + 5
    • Temukan tempat yang diidentifikasi oleh x
    • Salin x ke akumulator
    • Tambahkan 5 ke akumulator
  • Simpan hasilnya dalam x
    • Temukan tempat yang diidentifikasi oleh x
    • Salin akumulator ke sana

Tentu saja, optimasi bisa

  • jika "menemukan x" tidak memiliki efek samping, dua "penemuan" dapat dilakukan sekali (dan x menjadi alamat yang disimpan dalam register pointer)
  • dua salinan tersebut dapat dihilangkan jika ADD diterapkan &xsebagai ganti ke akumulator

sehingga membuat kode yang dioptimalkan bertepatan x += 5satu.

Tetapi ini dapat dilakukan hanya jika "menemukan x" tidak memiliki efek samping, sebaliknya

*(x()) = *(x()) + 5;

dan

*(x()) += 5;

secara semantik berbeda, karena x()efek samping (mengakui x()adalah fungsi melakukan hal-hal aneh di sekitar dan mengembalikan int*) akan diproduksi dua kali atau sekali.

Kesetaraan antara x = x + ydan x += ykarenanya karena kasus khusus di mana +=dan =diterapkan pada nilai-l langsung.

Untuk pindah ke Python, itu mewarisi sintaksis dari C, tetapi karena tidak ada terjemahan / optimasi SEBELUM eksekusi dalam bahasa yang ditafsirkan, hal-hal tidak harus begitu terkait erat (karena ada satu langkah penguraian yang kurang). Namun, seorang juru bahasa dapat merujuk ke rutinitas eksekusi yang berbeda untuk tiga jenis ekspresi, mengambil keuntungan dari kode mesin yang berbeda tergantung pada bagaimana ekspresi dibentuk dan pada konteks evaluasi.


Bagi yang suka lebih detail ...

Setiap CPU memiliki ALU (unit aritmatika-logis) yaitu, pada intinya, jaringan kombinatorial yang input dan outputnya "dicolokkan" ke register dan / atau memori tergantung pada opcode instruksi.

Operasi biner biasanya diimplementasikan sebagai "pengubah register akumulator dengan input yang diambil" di suatu tempat ", di mana suatu tempat dapat berada - di dalam aliran instruksi itu sendiri (khas untuk manifes kontan: ADD A 5) - di dalam registri lain (tipikal untuk ekspresi ekspresi dengan temporaries: eg ADD AB) - di dalam memori, pada alamat yang diberikan oleh register (tipikal pengambilan data misalnya: ADD A (H)) - H, dalam hal ini, berfungsi seperti penunjuk dereferencing.

Dengan kodesemu ini, x += 5adalah

ADD (X) 5

sementara x = x+5ini

MOVE A (X)
ADD A 5
MOVE (X) A

Artinya, x + 5 memberikan sementara yang kemudian ditugaskan. x += 5beroperasi langsung pada x.

Implementasi aktual tergantung pada set instruksi nyata dari prosesor: Jika tidak ada ADD (.) copcode, kode pertama menjadi yang kedua: tidak mungkin.

Jika ada opcode seperti itu, dan optimisasi diaktifkan, ekspresi kedua, setelah menghilangkan gerakan mundur dan menyesuaikan opcode register, menjadi yang pertama.

Emilio Garavaglia
sumber
90
+1 untuk satu-satunya jawaban yang menjelaskan bahwa ia digunakan untuk memetakan kode mesin yang berbeda (dan lebih efisien) di masa lalu.
Péter Török
11
@KeithThompson Itu benar tetapi orang tidak dapat menyangkal bahwa perakitan memiliki pengaruh besar terhadap desain bahasa C (dan selanjutnya semua bahasa gaya C)
MattDavey
51
Ehm, "+ =" tidak memetakan ke "inc" (memetakan ke "add"), "++" memetakan ke "inc".
Brendan
11
Dengan "20 tahun yang lalu", saya pikir maksud Anda "30 tahun yang lalu". Dan BTW, COBOL memiliki C mengalahkan 20 tahun lagi dengan: ADD 5 TO X.
JoelFan
10
Besar dalam teori; salah dalam fakta. X86 ASM INC hanya menambahkan 1, jadi itu tidak mempengaruhi operator "tambah dan tetapkan" yang dibahas di sini (ini akan menjadi jawaban yang bagus untuk "++" dan "-").
Mark Brackett
281

Tergantung pada bagaimana Anda berpikir tentang hal itu, sebenarnya lebih mudah dipahami karena lebih mudah. Ambil, misalnya:

x = x + 5 meminta pemrosesan mental "ambil x, tambahkan lima untuk itu, dan kemudian tetapkan nilai baru itu kembali ke x"

x += 5 dapat dianggap sebagai "naikkan x 5"

Jadi, ini bukan hanya istilah singkat, itu sebenarnya menggambarkan fungsi jauh lebih langsung. Saat membaca sekumpulan kode, lebih mudah dipahami.

Eric King
sumber
32
+1, saya sepenuhnya setuju. Saya masuk ke pemrograman sebagai anak-anak, ketika pikiran saya mudah ditempa, dan x = x + 5masih mengganggu saya. Ketika saya masuk matematika di usia yang lebih tua, itu lebih mengganggu saya. Menggunakan x += 5secara signifikan lebih deskriptif dan jauh lebih masuk akal sebagai ungkapan.
Polinomial
44
Ada juga kasus di mana variabel memiliki nama panjang: reallyreallyreallylongvariablename = reallyreallyreallylongvariablename + 1... oh noes !!! a typo
9
@ Matt Fenwick: Itu tidak harus nama variabel yang panjang; itu bisa menjadi semacam ekspresi. Itu cenderung lebih sulit untuk diverifikasi, dan pembaca harus menghabiskan banyak perhatian untuk memastikan mereka sama.
David Thornley
32
X = X + 5 adalah semacam peretasan ketika sasaran Anda adalah untuk menambah x pada 5.
JeffO
1
@ Polinomial Saya pikir saya menemukan konsep x = x + 5 sebagai seorang anak juga. Berusia 9 tahun jika saya ingat dengan benar - dan itu masuk akal bagi saya dan masih masuk akal bagi saya sekarang dan jauh lebih suka untuk x + = 5. Yang pertama jauh lebih verbose dan saya bisa membayangkan konsep lebih jelas - ide bahwa saya menetapkan x menjadi nilai sebelumnya x (apa pun itu) dan kemudian menambahkan 5. Saya kira otak yang berbeda bekerja dengan cara yang berbeda.
Chris Harrison
48

Setidaknya dengan Python , x += ydan x = x + ydapat melakukan hal-hal yang sama sekali berbeda.

Misalnya, jika kita lakukan

a = []
b = a

kemudian a += [3]akan menghasilkan a == b == [3], sedangkan a = a + [3]akan menghasilkan a == [3]dan b == []. Yaitu, +=memodifikasi objek di tempat (well, mungkin bisa, Anda dapat mendefinisikan __iadd__metode untuk melakukan hampir semua hal yang Anda suka), sambil =membuat objek baru dan mengikat variabel ke sana.

Ini sangat penting ketika melakukan pekerjaan numerik dengan NumPy , karena Anda sering berakhir dengan beberapa referensi ke berbagai bagian array, dan penting untuk memastikan Anda tidak secara tidak sengaja memodifikasi bagian dari array yang ada referensi lain, atau menyalin array yang tidak perlu (yang bisa sangat mahal).

James
sumber
4
1 untuk __iadd__: ada bahasa di mana Anda dapat membuat referensi berubah ke datastructure bisa berubah, di mana operator +=didefinisikan, misalnya scala: val sb = StringBuffer(); lb += "mutable structure"vs var s = ""; s += "mutable variable". lebih lanjut memodifikasi konten struktur data sementara yang terakhir membuat titik variabel ke yang baru.
domba terbang
43

Itu disebut idiom . Pemrograman idiom berguna karena mereka adalah cara yang konsisten untuk menulis konstruksi pemrograman tertentu.

Setiap kali seseorang menulis, x += yAnda tahu bahwa xitu bertambah oleh ydan bukan operasi yang lebih kompleks (sebagai praktik terbaik, biasanya saya tidak akan mencampur operasi yang lebih rumit dan steno sintaksis ini). Ini paling masuk akal saat ditambah 1.

Joe
sumber
13
x ++ dan ++ x sedikit berbeda dengan x + = 1 dan satu sama lain.
Gary Willoughby
1
@Gary: ++xdan x+=1setara dalam C dan Java (mungkin juga C #) meskipun tidak harus begitu dalam C ++ karena semantik operator yang kompleks di sana. Kuncinya adalah bahwa mereka berdua mengevaluasi xsatu kali, menambah variabel dengan satu, dan memiliki hasil yang merupakan isi dari variabel setelah evaluasi.
Donal Fellows
3
@Donal Fellows: Diutamakan berbeda, jadi ++x + 3tidak sama dengan x += 1 + 3. Kurung x += 1dan identik. Sebagai pernyataan sendiri, mereka identik.
David Thornley
1
@ Davidvidhorn: Sulit untuk mengatakan "mereka identik" ketika mereka berdua memiliki perilaku yang tidak jelas :)
Lightness Races in Orbit
1
Tidak ada ekspresi ++x + 3, x += 1 + 3atau (x += 1) + 3memiliki perilaku yang tidak terdefinisi (dengan asumsi nilai yang dihasilkan "cocok").
John Hascall
42

Untuk menempatkan poin @ Pubby sedikit lebih jelas, pertimbangkan someObj.foo.bar.func(x, y, z).baz += 5

Tanpa +=operator, ada dua cara:

  1. someObj.foo.bar.func(x, y, z).baz = someObj.foo.bar.func(x, y, z).baz + 5. Ini tidak hanya sangat berlebihan dan panjang, ini juga lebih lambat. Karena itu orang harus
  2. Menggunakan variabel sementara: tmp := someObj.foo.bar.func(x, y, z); tmp.baz = tmp.bar + 5. Ini baik-baik saja, tetapi banyak kebisingan untuk hal sederhana. Ini sebenarnya sangat dekat dengan apa yang terjadi pada saat runtime, tetapi membosankan untuk menulis dan hanya menggunakan +=akan menggeser pekerjaan ke kompiler / juru bahasa.

Keuntungan dari +=dan operator lainnya tidak dapat disangkal, sementara membiasakan diri dengan mereka hanyalah masalah waktu.

back2dos
sumber
Setelah Anda berada 3 level di dalam rantai objek, Anda dapat berhenti memperhatikan optimasi kecil seperti 1, dan kode berisik seperti 2. Sebaliknya, pikirkan desain Anda sekali lagi.
Dorus
4
@ Dorus: Ekspresi yang saya pilih hanyalah perwakilan sembarang untuk "ekspresi kompleks". Jangan ragu untuk menggantinya dengan sesuatu di kepala Anda, yang tidak ingin Anda ketahui;)
back2dos
9
+1: Ini adalah alasan utama pengoptimalan ini - selalu benar, tidak peduli seberapa rumit ekspresi sisi kiri.
S.Lott
9
Menempatkan kesalahan ketik di sana adalah ilustrasi yang bagus tentang apa yang bisa terjadi.
David Thornley
21

Memang benar bahwa itu lebih pendek dan lebih mudah, dan memang benar bahwa itu mungkin terinspirasi oleh bahasa assembly yang mendasarinya, tetapi alasan itu praktik terbaik adalah bahwa itu mencegah seluruh kelas kesalahan, dan itu membuatnya lebih mudah untuk meninjau kode dan memastikan apa fungsinya.

Dengan

RidiculouslyComplexName += 1;

Karena hanya ada satu nama variabel yang terlibat, Anda yakin apa yang dilakukan pernyataan itu.

Dengan RidiculouslyComplexName = RidiculosulyComplexName + 1;

Selalu ada keraguan bahwa kedua belah pihak persis sama. Apakah Anda melihat bug? Itu menjadi lebih buruk ketika langganan dan kualifikasi hadir.

Jamie Cox
sumber
5
Semakin buruk dalam bahasa di mana pernyataan tugas dapat secara implisit membuat variabel, terutama jika bahasa peka terhadap huruf besar-kecil.
supercat
14

Walaupun notasi + = idiomatik dan lebih pendek, ini bukan alasan mengapa lebih mudah dibaca. Bagian terpenting dari membaca kode adalah memetakan sintaks terhadap makna, dan semakin dekat sintaksinya dengan proses berpikir programmer, semakin mudah dibaca (ini juga alasan mengapa kode boilerplate buruk: bukan bagian dari pemikiran proses, tetapi masih perlu untuk membuat fungsi kode). Dalam hal ini, pemikirannya adalah "variabel kenaikan x sebesar 5", bukan "biarkan x menjadi nilai x ditambah 5".

Ada kasus-kasus lain di mana notasi yang lebih pendek buruk untuk keterbacaan, misalnya ketika Anda menggunakan operator ternary di mana ifpernyataan akan lebih sesuai.

tammmer
sumber
11

Untuk mengetahui mengapa operator-operator ini menggunakan bahasa 'C-style', ada kutipan dari K&R 1st Edition (1978), 34 tahun yang lalu:

Terlepas dari keringkasan, operator penugasan memiliki keuntungan karena mereka lebih sesuai dengan cara orang berpikir. Kami mengatakan "tambahkan 2 ke saya" atau "tambah saya dengan 2," tidak "ambil saya, tambahkan 2, lalu masukkan hasilnya kembali ke saya." Demikianlah i += 2. Selain itu, untuk ekspresi rumit seperti

yyval[yypv[p3+p4] + yypv[p1+p2]] += 2

operator penugasan membuat kode lebih mudah dipahami, karena pembaca tidak perlu memeriksa dengan susah payah bahwa dua ekspresi panjang memang sama, atau bertanya-tanya mengapa tidak. Dan operator penugasan bahkan dapat membantu kompiler untuk menghasilkan kode yang lebih efisien.

Saya pikir jelas dari bagian ini bahwa Brian Kernighan dan Dennis Ritchie (K&R), percaya bahwa operator penugasan majemuk membantu keterbacaan kode.

Sudah lama sejak K&R menulis itu, dan banyak 'praktik terbaik' tentang bagaimana orang harus menulis kode telah berubah atau berkembang sejak saat itu. Tetapi pertanyaan programmer ini .stackexchange adalah pertama kali saya dapat mengingat seseorang menyuarakan keluhan tentang keterbacaan tugas majemuk, jadi saya bertanya-tanya apakah banyak programmer menemukan mereka menjadi masalah? Kemudian lagi, saat saya mengetik ini pertanyaannya memiliki 95 upvotes, jadi mungkin orang menemukan mereka menggelegar ketika membaca kode.

Michael Burr
sumber
9

Selain keterbacaan, mereka sebenarnya melakukan hal yang berbeda: +=tidak perlu mengevaluasi operan kirinya dua kali.

Misalnya, expr = expr + 5akan evalaute exprdua kali (dengan asumsi exprtidak murni).

Pubby
sumber
Untuk semua kecuali kompiler aneh, itu tidak masalah. Kebanyakan kompiler cukup pintar untuk menghasilkan biner yang sama untuk expr = expr + 5danexpr += 5
vsz
7
@ vsz Tidak jika exprmemiliki efek samping.
Pubby
6
@vsz: Dalam C, jika exprmemiliki efek samping, maka expr = expr + 5 harus menjalankan efek samping tersebut dua kali.
Keith Thompson
@Ubby: jika memiliki efek samping, tidak ada masalah tentang "kenyamanan" dan "keterbacaan", yang merupakan inti dari pertanyaan awal.
vsz
2
Lebih baik hati-hati dengan pernyataan "efek samping" itu. Membaca dan menulis untuk volatileefek samping, dan x=x+5dan x+=5memiliki efek samping yang sama ketika xadalahvolatile
MSalters
6

Selain manfaat jelas yang dijelaskan orang lain dengan sangat baik, ketika Anda memiliki nama yang sangat panjang itu lebih kompak.

  MyVeryVeryVeryVeryVeryLongName += 1;

atau

  MyVeryVeryVeryVeryVeryLongName =  MyVeryVeryVeryVeryVeryLongName + 1;
Andrey Rubshtein
sumber
6

Ini singkat.

Ini jauh lebih pendek untuk diketik. Ini melibatkan lebih sedikit operator. Ini memiliki area permukaan lebih sedikit dan lebih sedikit kesempatan untuk kebingungan.

Ini menggunakan operator yang lebih spesifik.

Ini adalah contoh yang dibuat-buat, dan saya tidak yakin apakah kompiler yang sebenarnya mengimplementasikan ini. x + = y sebenarnya menggunakan satu argumen dan satu operator dan memodifikasi x pada tempatnya. x = x + y dapat memiliki representasi menengah x = z di mana z adalah x + y. Yang terakhir menggunakan dua operator, penjumlahan dan penugasan, dan variabel sementara. Operator tunggal membuatnya sangat jelas bahwa sisi nilai tidak bisa apa pun selain y dan tidak perlu ditafsirkan. Dan secara teoritis bisa ada beberapa CPU mewah yang memiliki operator plus-sama yang berjalan lebih cepat daripada operator plus dan operator penugasan secara seri.

Mark Canlas
sumber
2
Secara teoritis, secara teoretis. The ADDpetunjuk pada banyak CPU memiliki varian yang beroperasi langsung di register atau memori menggunakan register lainnya, memori atau konstanta sebagai ditambakan kedua. Tidak semua kombinasi tersedia (mis. Tambahkan memori ke memori), tetapi ada cukup banyak untuk berguna. Bagaimanapun, setiap kompiler dengan pengoptimal yang baik akan tahu untuk menghasilkan kode yang sama x = x + yseperti untuk x += y.
Blrfl
Karenanya "dibuat-buat".
Mark Canlas
5

Itu adalah ungkapan yang bagus. Apakah lebih cepat atau tidak tergantung pada bahasa. Dalam C, itu lebih cepat karena itu diterjemahkan ke instruksi untuk meningkatkan variabel di sisi kanan. Bahasa modern, termasuk Python, Ruby, C, C ++ dan Java semuanya mendukung op = sintaks. Ini kompak, dan Anda terbiasa dengan cepat. Karena Anda akan melihatnya secara keseluruhan dalam kode orang lain (OPC), Anda mungkin juga akan terbiasa dan menggunakannya. Inilah yang terjadi dalam beberapa bahasa lain.

Dalam Python, pengetikan x += 5masih menyebabkan pembuatan objek integer 1 (meskipun dapat diambil dari kumpulan) dan yatim piatu dari objek integer yang berisi 5.

Di Jawa, itu menyebabkan tacit cast terjadi. Coba ketikkan

int x = 4;
x = x + 5.2  // This causes a compiler error
x += 5.2     // This is not an error; an implicit cast is done.
ncmathsadist
sumber
Bahasa imperatif modern . Dalam bahasa fungsional (murni) x+=5memiliki makna sesedikit x=x+5; misalnya di Haskell, yang terakhir tidak menyebabkan xpenambahan sebesar 5 - malah menyebabkan loop rekursi tak terbatas. Siapa yang mau tulisan singkat untuk itu?
leftaroundabout
Ini tidak selalu lebih cepat sama sekali dengan kompiler modern: bahkan dalam C.
HörmannHH
Kecepatan +=tidak terlalu tergantung pada bahasa seperti tergantung pada prosesor . Misalnya, X86 adalah arsitektur dua alamat, hanya mendukung +=secara asli. Pernyataan seperti a = b + c;harus dikompilasi a = b; a += c;karena tidak ada instruksi yang dapat menempatkan hasil penambahan di tempat lain selain di tempat salah satu puncak. Arsitektur Power, sebaliknya, adalah arsitektur tiga alamat yang tidak memiliki perintah khusus untuk +=. Pada arsitektur ini, pernyataan a += b;dan a = a + b;selalu dikompilasi dengan kode yang sama.
cmaster
4

Operator seperti +=sangat berguna ketika Anda menggunakan variabel sebagai akumulator , yaitu total berjalan:

x += 2;
x += 5;
x -= 3;

Jauh lebih mudah dibaca daripada:

x = x + 2;
x = x + 5;
x = x - 3;

Dalam kasus pertama, secara konseptual, Anda mengubah nilai dalam x. Dalam kasus kedua, Anda menghitung nilai baru dan menetapkannya xsetiap waktu. Dan walaupun Anda mungkin tidak akan pernah menulis kode yang sesederhana itu, idenya tetap sama ... fokusnya adalah pada apa yang Anda lakukan pada nilai yang ada alih-alih menciptakan beberapa nilai baru.

Caleb
sumber
Bagi saya itu sangat berlawanan - varian pertama seperti kotoran di layar dan yang kedua bersih dan mudah dibaca.
Mikhail V
1
Sapuan yang berbeda untuk orang yang berbeda, @MikhailV, tetapi jika Anda baru dalam pemrograman, Anda dapat mengubah tampilan setelah beberapa saat.
Caleb
Saya tidak begitu baru dalam pemrograman, saya hanya berpikir Anda sudah terbiasa dengan + = notasi untuk waktu yang lama dan karena itu Anda dapat membacanya. Yang awalnya tidak membuatnya menjadi sintaksis yang terlihat bagus, sehingga operator + yang dikelilingi oleh spasi secara objektif lebih bersih daripada + = dan teman-teman yang semuanya hampir tidak dapat dibedakan. Bukannya jawaban Anda salah, tetapi orang tidak boleh terlalu mengandalkan kebiasaan sendiri membuat konsumsi betapa "mudahnya membaca".
Mikhail V
Perasaan saya adalah bahwa ini lebih tentang perbedaan konseptual antara mengumpulkan dan menyimpan nilai-nilai baru daripada tentang membuat ekspresi lebih kompak. Sebagian besar bahasa pemrograman imperatif memiliki operator yang sama, jadi saya tampaknya bukan satu-satunya yang merasa berguna. Tapi seperti yang saya katakan, stroke berbeda untuk orang yang berbeda. Jangan menggunakannya jika Anda tidak menyukainya. Jika Anda ingin melanjutkan diskusi, mungkin Obrolan Rekayasa Perangkat Lunak akan lebih sesuai.
Caleb
1

Pertimbangkan ini

(some_object[index])->some_other_object[more] += 5

D0 Anda benar-benar ingin menulis

(some_object[index])->some_other_object[more] = (some_object[index])->some_other_object[more] + 5
S.Lott
sumber
1

Jawaban yang lain menargetkan kasus yang lebih umum, tetapi ada alasan lain: Dalam beberapa bahasa pemrograman, ini bisa kelebihan beban; misalnya Scala .


Pelajaran Scala kecil:

var j = 5 #Creates a variable
j += 4    #Compiles

val i = 5 #Creates a constant
i += 4    #Doesn’t compile

Jika suatu kelas hanya mendefinisikan +operator, x+=ymemang merupakan jalan pintas dari x=x+y.

+=Namun, jika kelas overload , mereka tidak:

var a = ""
a += "This works. a now points to a new String."

val b = ""
b += "This doesn’t compile, as b cannot be reassigned."

val c = StringBuffer() #implements +=
c += "This works, as StringBuffer implements “+=(c: String)”."

Selain itu, operator +dan +=dua operator terpisah (dan bukan hanya ini: + a, ++ a, a ++, a + ba + = b juga merupakan operator yang berbeda); dalam bahasa di mana operator kelebihan muatan tersedia, ini dapat menciptakan situasi yang menarik. Sama seperti yang dijelaskan di atas - jika Anda akan membebani +operator untuk melakukan penambahan, ingatlah bahwa +=itu juga harus kelebihan beban.

domba terbang
sumber
"Jika sebuah kelas hanya mendefinisikan operator +, x + = y memang merupakan jalan pintas dari x = x + y." Tapi tentunya itu juga bekerja sebaliknya? Dalam C ++, itu sangat umum untuk pertama mendefinisikan +=dan kemudian menentukan a+bsebagai "membuat salinan a, menempatkan bdi atasnya menggunakan +=, mengembalikan salinan a".
leftaroundabout
1

Katakan sekali dan hanya sekali: di x = x + 1, saya katakan 'x' dua kali.

Tetapi jangan pernah menulis, 'a = b + = 1' atau kita harus membunuh 10 anak kucing, 27 tikus, seekor anjing dan seekor hamster.


Anda seharusnya tidak pernah mengubah nilai suatu variabel, karena membuatnya lebih mudah untuk membuktikan kode itu benar - lihat pemrograman fungsional. Namun jika Anda melakukannya, maka lebih baik tidak mengatakan hal-hal hanya sekali.

richard
sumber
"tidak pernah mengubah nilai variabel" Paradigma fungsional ?
Peter Mortensen