Bagaimana penanganan Python tentang jeda baris berbeda dari titik koma otomatis JavaScript?

41

Javascript memiliki fitur yang disebut Penyisipan Titik Koma Otomatis di mana pada dasarnya jika parser menemukan token yang tidak valid, dan token terakhir sebelum itu adalah garis putus, maka parser akan menyisipkan titik koma di mana linebreak berada. Ini memungkinkan Anda untuk pada dasarnya menulis semua kode javascript Anda tanpa titik koma, tetapi Anda harus mengetahui beberapa kasus tepi, sebagian besar jika Anda memiliki kata kunci kembali dan kemudian nilai yang ingin Anda kembalikan pada baris baru.

function test(){
    // This will return 'undefined', because return is a valid statement
    // and  "john" is a valid statement on its own.
    return 
          "john"
}

Karena gotcha ini ada puluhan artikel dengan judul seperti 'Penyisipan titik koma otomatis adalah Jahat', 'Selalu gunakan titik koma dalam Javascript' dll.

Tetapi dalam Python tidak ada yang pernah menggunakan titik koma dan memiliki gotcha yang persis sama.

def test():
    # This will return 'undefined', because return is a valid statement
    # and  "john" is a valid statement on its own.
    return 
    "john"

Kerjanya persis sama, namun tidak ada yang sangat takut dengan perilaku Python.

Saya pikir kasus di mana javascript berperilaku buruk cukup sedikit sehingga Anda harus dapat menghindarinya dengan mudah. Kembali + nilai pada baris baru? Apakah orang benar-benar melakukan itu?

Ada pendapat? Apakah Anda menggunakan titik koma di javascript dan mengapa?

Einar Egilsson
sumber
3
Itu tidak bekerja sama persis. Penyisipan titik koma tidak pergi ke mana pun baris baru, dalam JavaScript. Lihat contoh kedua di halaman Wikipedia ini . Titik koma tidak dimasukkan di mana baris baru dalam contoh itu.
Reid
1
Maksud saya bukan itu menggunakan titik koma dan tidak menggunakannya bekerja persis sama, intinya adalah bahwa kasus tepi di javascript dan python adalah sama. Tentu ada beberapa kasus tepi di mana Anda harus tahu apa yang terjadi. Artikel terbaik yang pernah saya baca tentang subjek ini: inimino.org/~inimino/blog/javascript_semicolons
Einar Egilsson
4
Saya menempatkan tanda koma di JavaScript karena alasan yang sama saya menggunakan titik dalam kalimat. Tentu penerjemah biasanya bisa memahami pernyataan Anda tanpa mereka tapi itu hanya bentuk yang buruk.
JD Isaacks
3
Anda dapat mempertimbangkan menulis python yang valid dalam contoh Anda. Indikator komentar adalah #, bukan `// '.
Aaron Dufour
2
"eksplisit selalu lebih baik daripada implisit"

Jawaban:

62

Alasannya adalah bahwa dalam Python, baris baru adalah cara yang jelas untuk memisahkan baris kode; ini adalah dengan desain, dan cara kerjanya telah dipikirkan secara menyeluruh. Sebagai hasilnya, kode python dapat dibaca dengan sempurna dan tidak ambigu tanpa penanda akhir pernyataan khusus (terlepas dari baris baru).

Javascript, di sisi lain, dirancang dengan sintaks mirip C dalam pikiran, di mana pernyataan selalu diakhiri dengan tanda titik koma. Untuk membuat bahasa lebih toleran terhadap kesalahan, ia mencoba menebak ke mana titik koma tambahan harus dibuat untuk membuat kode yang benar. Karena ini semacam retro-dipasang ke sintaks seperti C, itu tidak selalu berfungsi seperti yang diharapkan (kadang-kadang, penerjemah skrip menebak salah), dan dapat membuat kode yang cukup kontra-intuitif. \

Atau, berdebat dalam istilah "eksplisit lebih baik daripada implisit": Dalam Python, baris baru sudah sepenuhnya eksplisit, sedangkan dalam Javascript, ambigu, jadi Anda menambahkan tanda titik koma untuk membuatnya eksplisit.

tammmer
sumber
3
Oh, dan Anda dapat memasukkan kode dalam komentar menggunakan backquotes.
tdammers
1
Contoh yang baik dari kasus di mana penyisipan semi-kolon otomatis akan berakhir dengan melakukan hal-hal yang tidak terduga adalah ini: pastebin.com/aVeWGdya
HoLyVieR
5
Dalam python, aturannya cukup sederhana: pernyataan diakhiri dengan linebreak kecuali ada string multiline tertutup ("" ", '' '), dict tidak tertutup ({}), daftar tidak tertutup ([]), atau backslash segera sebelum linebreak Dalam javascript, aturannya secara signifikan lebih rumit
Aaron Dufour
5
Meliputi 99% kesalahan adalah cara yang baik untuk meninggalkan hanya yang sangat sulit ditemukan. Tidak apa-apa untuk meninggalkan mereka di python karena ada aturan mudah yang mencakup 100% masalah.
Aaron Dufour
1
@ Harun: Anda lupa "satu set kurung tertutup (())". (Tidak sepenuhnya "tuple tertutup" karena tanda kurung tidak hanya digunakan untuk tuple.)
JAB
28

Ada perbedaan yang cukup mendasar dari cara kerjanya di Python, saya pikir. Mengutip dari pos Einar Egilsson ditautkan ke: "tanda titik koma tidak tersirat pada akhir baris jika token pertama dari baris berikutnya dapat diuraikan sebagai bagian dari pernyataan yang sama".

Dalam Python, pemisah baris selalu mengakhiri pernyataan, kecuali dalam kasus-kasus tertentu yang cukup jelas seperti di dalam tanda kurung. Sebaliknya, JavaScript akan mencoba mem-parsing sebanyak mungkin baris sebelum mengakhiri pernyataan, yang berpotensi mengarah ke hal-hal seperti ini:

// Define a function and name it area.
area = function(r) {
    return r * r * 3.14159
}

// Fooled you! We're actually invoking it.
(14)
Henrik
sumber
8
Nah, inilah twist yang menyenangkan untuk yang satu ini. Ganti 14 dengan sesuatu seperti (a + 1) ? do_something() : do_something_else();dan tiba-tiba, area diatur ke nilai kembali do_something()atau do_something_else()dan Anda akan sangat bingung.
Reid
20

Saya sering meminimalkan JS-Files saya dalam mode produksi. Berarti, menghapus komentar dan linebreak.

Tanpa menggunakan titik koma, itu akan merusak Javascript saya.

Deradon
sumber
8
Oke, itu benar. Tetapi jika minimizer Anda adalah parser yang sebenarnya, parser yang sebenarnya bisa dimasukkan lagi jika diperlukan. Atau tidak hanya menghapus linebreak, => Anda menjaga linebreak, kehilangan titik koma, mereka kira-kira jumlah yang sama sehingga tidak ada yang hilang.
Einar Egilsson
2
@Einar Egilsson Closure Compiler memang melakukan ini.
seriousdev
1
Semua hal dianggap sama, baris baru adalah jumlah byte yang sama dengan titik koma. Minimizer Anda dapat menghapus semua baris baru, tetapi harus ada titik koma. Ini pertukaran yang adil.
Logan Bailey
3
@ Logo: Itu dengan asumsi satu byte baris baru, tentu saja ;-)
Cameron
1
Tentu saja, jika kita menggunakan Python alih-alih Javascript, kita harus lebih sedikit kode WAY untuk melakukan hal yang sama, jadi fakta bahwa semi-titik dua menggunakan beberapa byte kurang dari lekukan adalah titik diperdebatkan.
BlueRaja - Danny Pflughoeft
5

Itu tidak berfungsi seperti yang Anda gambarkan.

Javascript memiliki fitur yang disebut Penyisipan Titik Koma Otomatis di mana pada dasarnya jika parser menemukan token yang tidak valid, dan token terakhir sebelum itu adalah garis putus, maka parser akan menyisipkan titik koma di mana linebreak berada.

Ini salah. Contoh:

return
  1 + 2;

1adalah token yang benar-benar valid, tetapi parser akan tetap memasukkan tanda titik koma langsung setelahnya return.

Seperti yang Anda lihat, bahkan Anda tidak tahu persis di mana titik koma akan terjadi.

Masalah dengan penyisipan otomatis ada dua:

  • Untuk satu, orang mungkin meninggalkan titik koma di mana penyisipan otomatis tidak dapat menentukan bahwa seseorang harus dimasukkan.
  • Juga, tanda titik koma bisa dimasukkan di tempat yang tidak dimaksudkan, seperti di atas.

Tentu saja, menggunakan titik koma setelah setiap pernyataan hanya membantu dengan sumber kesalahan pertama.

Dalam hal apapun, seperti yang Anda duga sekarang, saya percaya bahwa penyisipan titik koma otomatis dalam sintaksis mirip-C adalah ide yang buruk.

Svante
sumber
1
ECMA Script spec secara eksplisit menentukan kasus mana yang akan disisipkan titik koma, sehingga baris Anda "Anda tidak dapat mengetahui dengan tepat di mana tanda titik koma akan terjadi" tidak benar. Masalahnya adalah bahwa hal itu tidak intuitif dalam beberapa kasus, membuatnya lebih sulit untuk mengajar seseorang yang tidak mengerti cara kerjanya.
zzzzBov
1
@zzzzBov: Ya, ada spesifikasi yang tepat, tetapi apakah ada yang benar-benar memiliki semua kasus dalam pikiran saat pengkodean? Apakah kamu yakin Pemrogram malas, dan memang seharusnya begitu; mereka tidak mau harus mengingat aturan yang rumit ketika yang lebih sederhana akan dilakukan. Jadi mereka berusaha menyiasati harus mengingatnya.
Svante
Saya setuju bahwa penyisipan semi-colon sebagian besar tidak perlu. Saya hanya mengatakan ada perbedaan antara mengatakan "Anda tidak tahu ke mana semi-titik dua akan pergi" dan "spesifikasi untuk penyisipan semi-kolon adalah campur aduk yang tidak intuitif"
zzzzBov
1
@Sante: Tapi contoh kembali menunjukkan kepada kita bahwa kita harus mengetahui aturan-aturan ini. Di sana Anda menggunakan titik koma tetapi itu tidak membantu Anda melakukan apa yang Anda inginkan. Jadi, mengingat bahwa bahasa memiliki fitur ini, kami memiliki pilihan untuk (1) Menulis titik koma di mana-mana dan mengetahui aturan sehingga kami memahami apa yang akan terjadi (2) Tidak menulis titik koma di mana-mana, dan memahami aturan sehingga kami memahami apa yang akan terjadi. Diberi pilihan itu, saya pikir saya lebih baik melewatkan titik koma
Einar Egilsson
4

Saya akan menyatakan satu alasan sederhana:

Javascript terlihat "agak java-ish" atau "agak C-ish". Tentu saja itu bahasa yang dinamis sehingga terlihat berbeda ... tetapi hadapi itu - Ada kawat gigi. Bahasa dengan kawat gigi umumnya memiliki titik koma. Refleks alami menendang dan membuat jari Anda mengarah ke tombol titik koma sebelum Anda menekan Enter.

Python, sebaliknya, bahkan sekilas terlihat sangat berbeda. Oleh karena itu, sedikit atau tidak ada analogi dengan "bahasa standar membosankan" secara intuitif dibentuk dan ketika seseorang memasuki "mode python", kurangnya titik koma menjadi alami.

Kos
sumber
2

Ada sejumlah alasan bagus untuk tidak menggunakan penyisipan semi-usus besar dalam JavaScript.

Terutama itu karena penyisipan semi-kolon sebagaimana didefinisikan dalam standar ECMAScript tidak intuitif untuk beberapa kasus. @Svante menunjukkan kasus di returnmana penggunaan baris baru akan menyebabkan masalah.

Yang tidak dia sebutkan adalah bahwa itu akan menyebabkan masalah jika Anda menggunakan semi-titik dua juga, karena penyisipan semi-titik dua terjadi apakah Anda menginginkannya atau tidak.

Alasan lain yang sangat bagus untuk tidak menggunakan penyisipan semi-kolon adalah kontrol output. Dalam banyak kasus, JavaScript dijalankan melalui minifier sebelum digunakan dalam produksi. Beberapa minifiers mungkin menangani kasus penyisipan semi-kolon otomatis, tapi saya tidak melihat alasan untuk mengandalkannya bekerja dengan sempurna

Selain itu untuk sistem manajemen konten, JavaScript sebaris mungkin diperkecil secara otomatis, dan saya telah melihat sejumlah kasus di mana penjelas otomatis hanya menghapus komentar dan memotong spasi putih (termasuk baris baru) dari awal dan akhir setiap baris.

Bagi penulis yang tidak memiliki pilihan alat apa yang dipilih, jauh lebih mudah untuk hanya berpegang pada format yang berfungsi di sebagian besar kasus.

zzzzBov
sumber
Ah, maaf, tapi mengenai ayat ketiga, saya lakukan menyebutkan bahwa dalam kedua-untuk-terakhir kalimat saya. :)
Svante
Ya, masalah perkakas ini valid (meskipun minifiers yang baik harus menangani hal ini, misalnya kompiler Penutupan). Tetapi menurut saya, kita perlu mengetahui aturan-aturan ini, untuk menghindari hal-hal seperti contoh 'kembali'. Dan begitu saya tahu aturannya, saya mungkin juga menggunakan fitur ini, terutama karena itu membuat kode (IMO) lebih mudah dibaca.
Einar Egilsson
1

Tidak menggunakan titik koma adalah resep untuk kegagalan ketika Anda mengecilkan file Anda file JavaScript. Itu sebabnya saya takut akan hal itu.

Biksu Timur
sumber
1

Dalam Javascript, Anda dapat menulis program yang secara sintaksis benar tanpa adanya penyisipan titik koma otomatis, dan ASI akan mengubah program itu menjadi program yang benar secara sintaksis yang berbeda (misalnya, mengubah kode yang mengembalikan nilai menjadi kode yang tidak menghasilkan apa-apa). Tidak ada kasus analog dengan Python. Dengan Python baris baru apa pun yang bisa mengakhiri pernyataan akan mengakhiri pernyataan, kecuali jika lolos dengan garis miring terbalik. Secara teknis, saya kira aturan Javascript sama-sama deterministik, tapi saya tidak tahu apakah Anda bisa meringkas aturan Javascript untuk mengakhiri pernyataan dalam satu kalimat.

Ryan C. Thompson
sumber
1

Dalam kebanyakan kasus, ASI JavaScript menangani hal-hal seperti yang diharapkan. Salah satu contoh ASI yang mungkin tidak berlaku seperti yang Anda harapkan adalah ini:

var i = 0

(function() {
   // do something
})()

Ini akan ditafsirkan sebagai memanggil fungsi 0dengan fungsi anonim, kemudian mengeksekusi hasilnya. Dalam hal ini Anda mungkin ingin melakukan tugas, lalu segera jalankan fungsi anonim.

Untuk seseorang yang tidak terbiasa dengan ASI bisa sangat membingungkan ketika Anda mengalami masalah seperti ini, jadi saya selalu merekomendasikan pengembang di tim saya untuk menggunakan titik koma.

(Sebagai tambahan: Saya tidak menggunakan titik koma ketika mengerjakan proyek pribadi / sisi karena saya tahu tidak ada orang lain yang perlu mempertahankan kode.)

jay_soo
sumber
1

Seperti Anda, saya pikir itu agak paranoid. Aturan untuk penyisipan titik koma didefinisikan dengan baik dalam JavaScript, seperti halnya dalam Python dan CoffeeScript. Tidak ada yang membuang Python atau CoffeeScript dengan titik koma, jadi mengapa JavaScript diperlakukan berbeda?

Saya pikir ini merupakan reaksi berlebihan terhadap kondisi buruk kode JavaScript tipikal dari sekitar sepuluh tahun yang lalu — JavaScript dipandang sebagai bahasa yang lemah, bermasalah, jelek, tidak baik. Itu memalukan. Anda tidak mungkin menulis kode yang baik dalam JavaScript!

Kemudian, orang-orang datang dan mencoba membuktikan bahwa Anda dapat menulis kode yang indah dan jelas dalam JavaScript. Aturan " selalu gunakan titik koma" adalah bagian dari wave ini. Dan sejujurnya, itu bisa membuat beberapa situasi sedikit lebih jelas.

Mengapa JavaScript masih diperlakukan berbeda?

Ada kelembaman. Dan tidak boleh diabaikan bahwa orang yang menghargai kode terstruktur secara eksplisit sering lebih suka bahasa gaya-C. Orang yang menghargai kode terstruktur tersirat sering berpindah ke bahasa non-C-style (seperti CoffeeScript).

Koboi Penutupan
sumber
0

Saya menggunakannya dalam Javascript secara ketat untuk konsistensi. Jika sebagian besar garis memiliki

Python memiliki mereka untuk kasus tepi seperti beberapa pernyataan pada satu baris, javascript memilikinya dan karena Anda akan menemukan mereka secara teratur digunakan saya sesuai dengan norma di mana mereka digunakan.

Saya tidak dapat menemukan penggunaan untuk beberapa pernyataan pada baris yang sama dan karena itu jangan melihat menggunakan titik koma.

Chris
sumber
Ya, saya telah memperbaiki contoh Python. Tapi intinya tetap, Python juga memiliki titik koma, Anda dipersilakan untuk menempatkan mereka setelah setiap pernyataan (dan harus jika Anda memiliki lebih dari satu di setiap baris) tetapi orang tidak menggunakannya.
Einar Egilsson
0

Jika Anda menggunakan sesuatu seperti bundle-fu, dan manajer aset untuk aplikasi web Anda di rails, maka itu akan rusak parah jika tidak menemukan tanda titik koma di akhir token dalam javascript. Jadi, ini adalah praktik yang baik untuk menerapkannya.

subiet
sumber
Tiga besar, Kompresor YUI, Kompresor Penutupan, dan UglifyJS, semuanya melakukan penyisipan titik koma. Saya tidak terkejut bahwa pelabuhan ruby ​​JSMin memiliki masalah.
Benjamin Atkin
0

Saya tidak ingat versi IE mana yang tepat, tetapi ada beberapa kasus di mana IE akan benar-benar keluar jika titik koma tidak ada. IIRC ketika Anda memiliki sesuatu dalam lingkup global seperti:

var myFunc = function() {
  ...
}

Jika Anda tidak menambahkan; setelah kurung kurawal, program akan benar-benar gagal pada beberapa versi IE. Itu, bersama dengan alasan lain (termasuk rekomendasi Crockford untuk selalu menggunakannya secara eksplisit) telah mendorong saya untuk selalu menggunakannya secara eksplisit dalam setiap kasus.

apinstein
sumber