Mungkin saya bukan dari planet ini, tetapi bagi saya tampaknya hal berikut ini adalah kesalahan sintaksis:
int a[] = {1,2,}; //extra comma in the end
Tapi ternyata tidak. Saya terkejut ketika kode ini dikompilasi pada Visual Studio, tapi saya telah belajar untuk tidak mempercayai MSVC compiler sejauh C ++ aturan yang bersangkutan, jadi aku memeriksa standar dan itu adalah diperbolehkan oleh standar juga. Anda dapat melihat 8.5.1 untuk aturan tata bahasa jika Anda tidak percaya kepada saya.
Kenapa ini diizinkan? Ini mungkin pertanyaan bodoh yang tidak berguna tapi saya ingin Anda mengerti mengapa saya bertanya. Jika itu adalah sub-kasus aturan tata bahasa umum, saya akan mengerti - mereka memutuskan untuk tidak membuat tata bahasa umum lebih sulit hanya untuk melarang koma yang berlebihan pada akhir daftar penginisialisasi. Tapi tidak, koma tambahan diizinkan secara eksplisit . Sebagai contoh, itu tidak diperbolehkan untuk memiliki koma yang berlebihan di akhir daftar argumen fungsi-panggilan (ketika fungsi mengambil ...
), yang normal .
Jadi, sekali lagi, apakah ada alasan khusus koma yang berlebihan ini diizinkan secara eksplisit ?
sumber
;
ketika jelas token berikutnya sebenarnya adalah pernyataan berikutnya.for()
contoh), menambahkannya melemparkan peringatan kompiler.if (x = 1)
tidak ambigu dalam tata bahasa, tetapi sangat ambigu bagi manusia, dan dengan demikian melemparkan peringatan.if
Contoh Anda juga tidak ambigu. Saya tidak berpikir "ambigu" berarti apa yang Anda pikirkan artinya!Jawaban:
Itu membuatnya lebih mudah untuk menghasilkan kode sumber, dan juga untuk menulis kode yang dapat dengan mudah diperpanjang di kemudian hari. Pertimbangkan apa yang diperlukan untuk menambahkan entri tambahan ke:
... Anda harus menambahkan koma ke baris yang ada dan menambahkan baris baru. Bandingkan dengan kasus di mana ketiganya sudah memiliki koma setelahnya, di mana Anda hanya perlu menambahkan baris. Demikian juga jika Anda ingin menghapus garis, Anda dapat melakukannya tanpa khawatir tentang apakah itu baris terakhir atau tidak, dan Anda dapat memesan ulang garis tanpa mengotak-atik koma. Pada dasarnya itu berarti ada keseragaman dalam cara Anda memperlakukan garis.
Sekarang pikirkan tentang menghasilkan kode. Sesuatu seperti (pseudo-code):
Tidak perlu khawatir tentang apakah item yang sedang Anda tulis adalah yang pertama atau yang terakhir. Jauh lebih sederhana.
sumber
Ini berguna jika Anda melakukan sesuatu seperti ini:
sumber
var a = [1, 2,];
demikian juga sebagian besar bahasa lain yang saya tahu ... ActionScript, Python, PHP.undefined
.Kemudahan penggunaan untuk pengembang, saya akan berpikir.
Selain itu, jika karena alasan apa pun Anda memiliki alat yang menghasilkan kode untuk Anda; alat tidak perlu peduli apakah itu item terakhir di inisialisasi atau tidak.
sumber
Saya selalu berasumsi akan membuatnya lebih mudah untuk menambahkan elemen tambahan:
hanya menjadi:
di kemudian hari.
sumber
[1,2,3,]
OK tapi{a:1, b:2, c:3,}
tidak).Segala sesuatu yang dikatakan semua orang tentang kemudahan menambah / menghapus / menghasilkan baris sudah benar, tetapi tempat sebenarnya sintaks ini bersinar adalah ketika menggabungkan file sumber menjadi satu. Bayangkan Anda memiliki array ini:
Dan anggap Anda telah memeriksa kode ini ke dalam repositori.
Kemudian teman Anda mengeditnya, dan menambahkannya di akhir:
Dan Anda secara bersamaan mengeditnya, menambahkan ke awal:
Semantik operasi semacam ini (menambah awal, menambah akhir) harus sepenuhnya menggabungkan aman dan perangkat lunak versi Anda (mudah-mudahan git) harus dapat diotomatiskan. Sayangnya, ini bukan masalahnya karena versi Anda tidak memiliki koma setelah angka 9 dan versi teman Anda tidak. Padahal, jika versi asli memiliki 9 trailing, mereka akan otomatis.
Jadi, aturan praktis saya adalah: gunakan koma trailing jika daftar tersebut mencakup beberapa baris, jangan gunakan itu jika daftar berada pada satu baris.
sumber
Trailing koma saya percaya diperbolehkan untuk alasan kompatibilitas ke belakang. Ada banyak kode yang ada, terutama yang dibuat secara otomatis, yang menempatkan tanda koma. Itu membuatnya lebih mudah untuk menulis loop tanpa syarat khusus pada akhirnya. misalnya
Sebenarnya tidak ada keuntungan bagi programmer.
PS Meskipun lebih mudah untuk membuat kode secara otomatis dengan cara ini, saya sebenarnya selalu berhati-hati untuk tidak menempatkan koma trailing, upaya minimal, keterbacaan ditingkatkan, dan itu lebih penting. Anda menulis kode sekali, Anda membacanya berkali-kali.
sumber
int a = b + c +;
atauif(a && b &&);
akan lebih mudah untuk hanya menyalin dan menempelkan apa saja di akhir dan lebih mudah untuk menulis generator kode. Masalah ini sepele, dan subyektif, dalam kasus seperti itu selalu baik untuk melakukan yang terbaik untuk pembaca kode.&&
operator, kadang-kadang saya melakukan conditional sepertiif (true \n && b1 \n && b2)
sehingga saya dapat menambah dan menghapus garis yang saya butuhkan.Salah satu alasan ini diizinkan sejauh yang saya tahu adalah bahwa itu harus mudah untuk secara otomatis menghasilkan kode; Anda tidak memerlukan penanganan khusus untuk elemen terakhir.
sumber
Itu membuat generator kode yang mengeluarkan array atau enumerasi lebih mudah.
Membayangkan:
Yaitu, tidak perlu melakukan penanganan khusus pada item pertama atau terakhir untuk menghindari meludah koma tertinggal.
Jika pembuat kode ditulis dengan Python, misalnya, mudah untuk menghindari meludah koma trailing dengan menggunakan
str.join()
fungsi:sumber
Saya terkejut setelah selama ini tidak ada yang mengutip Annotated C ++ Reference Manual ( ARM ), ia mengatakan yang berikut tentang [dcl.init] dengan penekanan pada saya:
meskipun tata bahasanya telah berevolusi sejak ARM ditulis, asalnya tetap.
dan kita bisa pergi ke alasan C99 untuk melihat mengapa ini diizinkan di C dan dikatakan:
sumber
Saya melihat satu kasus penggunaan yang tidak disebutkan dalam jawaban lain, makro favorit kami:
Menambahkan makro ke pegangan terakhir
,
akan sangat menyakitkan. Dengan perubahan kecil dalam sintaks ini mudah untuk dikelola. Dan ini lebih penting daripada kode yang dihasilkan mesin karena biasanya lebih mudah untuk melakukannya di Turing langue daripada preprocesor yang sangat terbatas.sumber
Satu-satunya bahasa di mana itu - dalam praktek * - tidak diperbolehkan adalah Javascript, dan itu menyebabkan jumlah masalah yang tak terhitung. Misalnya, jika Anda menyalin & menempelkan baris dari tengah array, menempelnya di akhir, dan lupa menghapus koma maka situs Anda akan benar-benar rusak untuk pengunjung IE Anda.
* Secara teori diizinkan tetapi Internet Explorer tidak mengikuti standar dan memperlakukannya sebagai kesalahan
sumber
var x = [,,,]
legal (kecuali dalam IE <9, tetapi spek itu mengatakan itu legal)Lebih mudah untuk mesin, yaitu parsing dan pembuatan kode. Ini juga lebih mudah bagi manusia, yaitu modifikasi, komentar, dan keanggunan visual melalui konsistensi.
Dengan asumsi C, apakah Anda akan menulis yang berikut ini?
Tidak. Bukan hanya karena pernyataan akhir adalah kesalahan, tetapi juga karena itu tidak konsisten. Jadi mengapa melakukan hal yang sama pada koleksi? Bahkan dalam bahasa yang memungkinkan Anda menghilangkan tanda koma dan koma terakhir, komunitas biasanya tidak menyukainya. Komunitas Perl, misalnya, tampaknya tidak suka menghilangkan tanda titik koma, baris satu baris. Mereka menerapkannya pada koma juga.
Jangan hilangkan koma dalam koleksi multiline karena alasan yang sama Anda tidak menghilangkan koma untuk blok kode multiline. Maksud saya, Anda tidak akan melakukannya bahkan jika bahasa itu memungkinkan, bukan? Baik?
sumber
Alasannya sepele: kemudahan menambah / menghapus garis.
Bayangkan kode berikut:
Sekarang, Anda dapat dengan mudah menambahkan / menghapus item ke daftar tanpa harus menambahkan / menghapus koma sesekali.
Berbeda dengan jawaban lain, saya tidak benar-benar berpikir bahwa kemudahan membuat daftar adalah alasan yang valid: setelah semua, itu sepele untuk kode untuk kasus-khusus baris terakhir (atau pertama). Generator kode ditulis satu kali dan digunakan berkali-kali.
sumber
Ini memungkinkan setiap baris untuk mengikuti formulir yang sama. Pertama, ini memudahkan untuk menambahkan baris baru dan memiliki sistem kontrol versi melacak perubahan secara bermakna dan juga memungkinkan Anda untuk menganalisis kode dengan lebih mudah. Saya tidak bisa memikirkan alasan teknis.
sumber
Ini diperbolehkan untuk melindungi dari kesalahan yang disebabkan oleh elemen yang bergerak dalam daftar panjang.
Misalnya, mari kita asumsikan kita memiliki kode yang terlihat seperti ini.
Dan itu bagus, karena menunjukkan trilogi asli dari situs-situs Stack Exchange.
Tapi ada satu masalah dengan itu. Anda lihat, catatan kaki di situs web ini menunjukkan Kesalahan Server sebelum Pengguna Super. Lebih baik memperbaikinya sebelum ada yang tahu.
Lagipula, memindahkan garis di sekitar tidak mungkin sulit, bukan?
Saya tahu, tidak ada situs web yang disebut "Pengguna Server FaultSuper", tetapi kompiler kami mengklaim itu ada. Sekarang, masalahnya adalah bahwa C memiliki fitur penggabungan string, yang memungkinkan Anda untuk menulis dua string yang dikutip ganda dan menggabungkannya dengan tidak menggunakan apa pun (masalah serupa juga dapat terjadi dengan bilangan bulat, seperti
-
tanda memiliki beberapa makna).Sekarang bagaimana jika array asli memiliki koma yang tidak berguna di akhir? Yah, garis akan dipindahkan, tetapi bug seperti itu tidak akan terjadi. Sangat mudah untuk melewatkan sesuatu sekecil koma. Jika Anda ingat untuk meletakkan koma setelah setiap elemen array, bug seperti itu tidak bisa terjadi. Anda tidak ingin membuang empat jam untuk men-debug sesuatu, sampai Anda menemukan bahwa koma adalah penyebab masalah Anda .
sumber
Seperti banyak hal, koma jejak dalam penginisialisasi array adalah salah satu hal yang diwarisi oleh C ++ dari C (dan harus didukung selamanya). Pandangan yang sama sekali berbeda dari yang ditempatkan di sini disebutkan dalam buku "Rahasia C mendalam" .
Setelah itu ada contoh dengan lebih dari satu "koma paradoks":
kita membaca :
... bagi saya ini lebih masuk akal
sumber
enum
kasus ini agak menarik, karena itulah kasus di mana koma yang hilang akan menimbulkan ambiguitas paling sedikit. Diberikanstruct foo arr[] = {{1,2,3,4,5}, {3,4,5,6,7}, }
; ada dua arti yang masuk akal yang dapat diberikan oleh bahasa: buat array dua elemen, atau buat array tiga elemen di mana item terakhir memiliki nilai default. Jika C mengadopsi interpretasi yang kemudian, saya bisa melihat melarangenum foo {moe, larry, curly, };
pada prinsip bahwa seharusnya hanya ada satu cara untuk menulis pernyataan (tanpa koma), tapi ...enum foo {moe,,larry,curly,};
sebagai melewatkan angka di antaramoe
danlarry
, umumnya tidak masalah apakah koma tertinggal diproses atau diabaikan. Satu-satunya kasus di mana itu bisa menjadi masalah adalah jika item terakhir adalah nilai maksimum untuk jenis yang dinyatakan, dan itu ...Selain pembuatan kode dan kemudahan pengeditan, jika Anda ingin mengimplementasikan parser, jenis tata bahasa ini lebih sederhana dan lebih mudah diimplementasikan. C # mengikuti aturan ini di beberapa tempat yang ada daftar item yang dipisahkan koma, seperti item dalam
enum
definisi.sumber
Itu membuat menghasilkan kode lebih mudah karena Anda hanya perlu menambahkan satu baris dan tidak perlu memperlakukan menambahkan entri terakhir seolah-olah itu kasus khusus. Ini terutama benar ketika menggunakan makro untuk menghasilkan kode. Ada dorongan untuk mencoba menghilangkan kebutuhan makro dari bahasa tersebut, tetapi banyak bahasa yang berkembang seiring dengan makro tersedia. Koma ekstra memungkinkan makro seperti yang berikut ini untuk didefinisikan dan digunakan:
Pemakaian:
Itu contoh yang sangat sederhana, tetapi sering pola ini digunakan oleh makro untuk mendefinisikan hal-hal seperti pengiriman, pesan, acara atau peta dan tabel terjemahan. Jika koma tidak diizinkan di akhir, kami akan membutuhkan spesial:
dan itu akan sangat canggung untuk digunakan.
sumber
Sehingga ketika dua orang menambahkan item baru dalam daftar di cabang terpisah, Git dapat menggabungkan perubahan dengan benar, karena Git bekerja berdasarkan garis.
sumber
Jika Anda menggunakan array tanpa panjang yang ditentukan, VC ++ 6.0 dapat secara otomatis mengidentifikasi panjangnya, jadi jika Anda menggunakan "int a [] = {1,2,};" panjang a adalah 3, tetapi yang terakhir tidak memiliki t diinisialisasi, Anda dapat menggunakan "cout <
sumber