Apakah bahasa lain selain JavaScript memiliki perbedaan antara lokasi awal tanda kurung kurawal (baris yang sama dan baris berikutnya)?

91

Hari ini, ketika saya secara acak membaca buku pola JavaScript O'Reilly, saya menemukan satu hal yang menarik (halaman 27 untuk referensi).

Dalam Javascript, dalam beberapa kasus, terdapat perbedaan jika lokasi awal brace berbeda.

function test_function1() {
    return
    {
        name: 'rajat'
    };
}

var obj = test_function1();
alert(obj);  //Shows "undefined"

Sementara

function test_function2() {
    return {
        name: 'rajat'
    };
}

var obj = test_function2();
alert(obj); //Shows object

Demo JSfiddle

Apakah ada bahasa lain di luar sana yang memiliki perilaku seperti itu? Jika demikian, maka saya pasti harus mengubah kebiasaan saya .. :)

Saya terutama peduli tentang PHP, C, C ++, Java, dan ruby.

Rajat Singhal
sumber
1
Direproduksi di Chrome dan IE9, hasil yang bagus: P
gideon
4
Sensitivitas white space dapat dibuat berfungsi --- lihat python atau mode garis fortran --- tetapi sensitivitas white space yang halus adalah karya iblis. Gah! Ini seburuk make!
dmckee --- mantan moderator anak kucing
Ini luar biasa! Temuan bagus!
CheckRaise
Sekarang saya ingin tahu mengapa javascript berperilaku seperti ini.
CheckRaise
4
@CheckRaise: Saya merangkum aturannya di sini: blogs.msdn.com/b/ericlippert/archive/2004/02/02/…
Eric Lippert

Jawaban:

53

Setiap bahasa yang tidak bergantung pada titik koma (tapi bukan pada baris) atas laporan membatasi berpotensi memungkinkan ini. Pertimbangkan Python :

>>> def foo():
...   return
...   { 1: 2 }
... 
>>> def bar():
...   return { 1: 2 }
... 
>>> foo()
>>> bar()
{1: 2}

Anda mungkin dapat membuat kasus serupa dalam Visual Basic tetapi di luar kepala saya, saya tidak tahu bagaimana karena VB cukup membatasi di mana nilai dapat ditempatkan. Tetapi hal berikut seharusnya berfungsi, kecuali penganalisis statis mengeluh tentang kode yang tidak dapat dijangkau:

Try
    Throw New Exception()
Catch ex As Exception
    Throw ex.GetBaseException()
End Try

' versus

Try
    Throw New Exception()
Catch ex As Exception
    Throw
    ex.GetBaseException()
End Try

Dari bahasa yang Anda sebutkan, Ruby memiliki properti yang sama. PHP, C, C ++ dan Java tidak hanya karena mereka membuang baris baru sebagai spasi, dan memerlukan titik koma untuk membatasi pernyataan.

Berikut kode yang setara dari contoh Python di Ruby:

>> def foo
>>   return { 1 => 2 }
>> end
=> nil
>> def bar
>>   return
>>   { 1 => 2 }
>> end
=> nil
>> foo
=> {1=>2}
>> bar
=> nil
Konrad Rudolph
sumber
2
Contoh VB Anda tidak cukup tepat karena VB tidak pernah mengizinkan pernyataan untuk menjangkau beberapa baris kecuali Anda menggunakan urutan garis-lanjutan "_".
phoog
2
Ok saya menarik kembali komentar sebelumnya karena saya hanya melihat spesifikasi ada beberapa konteks di mana VB.NET mendukung kelanjutan baris implisit. Saya ragu setiap programmer VB berpengalaman akan menganggap contoh ini sebagai "gotcha", bagaimanapun, karena itu cukup jelas Throwdan ex.GetBaseException()merupakan garis logis yang terpisah. Lebih khusus lagi, karena Basic secara historis menggunakan baris untuk membatasi pernyataannya, "gotcha" kemungkinan besar akan menjadi situasi di mana programmer mengira dia membuat pernyataan baru pada baris logis baru, tetapi belum.
phoog
@phoog Benar, ini sama sekali bukan gotcha.
Konrad Rudolph
40

Penerjemah JavaScript secara otomatis menambahkan a ;di akhir setiap baris jika tidak menemukannya (dengan beberapa pengecualian, tidak masuk ke sini :).

Jadi pada dasarnya masalahnya bukanlah lokasi kurung kurawal (yang di sini mewakili literal objek, bukan blok kode seperti dalam kebanyakan bahasa), tetapi "fitur" kecil ini yang memaksa contoh pertama Anda ke return ;=> undefined. Anda dapat memeriksa perilaku return di spesifikasi ES5 .

Untuk bahasa lain yang memiliki perilaku serupa, lihat jawaban Konrad .

Alex Ciminian
sumber
5
Jawaban yang sangat disukai, namun sebenarnya salah, maaf. Penjelasannya bagus tapi tolong perbaiki kesalahannya.
Konrad Rudolph
Bagian tentang JavaScript tidak salah, cara perilakunya seperti itu adalah karena penyisipan titik koma yang memaksa undefineduntuk dikembalikan. Saya menulis sedikit tentang bahasa lain yang diawali dengan afaik , jadi ambillah dengan sebutir garam :).
Alex Ciminian
5
Tetapi tidak benar bahwa JS menyisipkan titik koma "di akhir setiap baris" "dengan beberapa pengecualian"; bukan, biasanya tidak memasukkan titik koma, dan hanya ada beberapa kasus di mana tidak . Itulah mengapa hal itu menyebabkan begitu banyak gangguan.
ruakh
26

Hampir dipastikan. Bahasa pemrograman go Google menunjukkan perilaku yang sangat mirip (meskipun dengan efek yang berbeda). Seperti yang dijelaskan di sana:

Faktanya, yang terjadi adalah bahasa formal menggunakan titik koma, seperti di C atau Java, tetapi disisipkan secara otomatis di akhir setiap baris yang terlihat seperti akhir pernyataan. Anda tidak perlu mengetiknya sendiri.

..menggunting...

Pendekatan ini menghasilkan kode yang tampak bersih dan bebas titik koma. Kejutannya adalah bahwa penting untuk meletakkan kurung kurawal buka dari sebuah konstruksi seperti pernyataan if pada baris yang sama dengan if; jika tidak, ada situasi yang mungkin tidak dapat dikompilasi atau mungkin memberikan hasil yang salah. Bahasa memaksa gaya brace sampai batas tertentu.

Secara diam-diam, saya pikir Rob Pike hanya menginginkan alasan untuk meminta One True Brace Style.

Dave
sumber
10
Keren, tidak tahu tentang ini :). Secara pribadi, menurut saya penyisipan titik koma otomatis bukanlah ide yang bagus. Ini dapat memperkenalkan bug halus yang akan sulit dipahami oleh orang yang tidak berpengalaman dengan bahasa tersebut. Jika Anda ingin menulis kode bebas titik koma, saya lebih suka cara python.
Alex Ciminian
@ Alex bahasa Bahkan tanpa setiap titik koma (VB) memiliki properti ini. Begitu pula dengan Python, yang tampaknya Anda sukai, meskipun menangani ini secara identik dengan JavaScript.
Konrad Rudolph
Saya akan memberi suara positif, kecuali bahwa kalimat kedua Anda sepenuhnya salah sehingga membuat saya ingin memberi suara negatif. Saya kira mereka membatalkan. ;-)
ruakh
1
@ruakh maksud Anda "lakukan persis seperti ini" atau apakah Anda mengacu pada lelucon tentang rob pike? Dalam kasus pertama, saya dapat mengubah kata-kata menjadi "pergi menunjukkan perilaku yang sama", dalam kasus terakhir, saya minta maaf jika selera humor saya yang lemah menyinggung;)
Dave
1
Maksud saya, "Go melakukan persis seperti ini." Proposal asli untuk penyisipan titik koma Go secara eksplisit kontras dengan JavaScript, menjelaskan, "Proposal ini mungkin mengingatkan Anda tentang aturan titik koma opsional JavaScript, yang pada dasarnya menambahkan titik koma untuk memperbaiki kesalahan penguraian. Proposal Go sangat berbeda", dan itu adalah benar, pada setiap level: ia bekerja secara berbeda, ia memiliki efek yang berbeda, dan hampir tidak ada gotcha. (Penegakan OTBS, meskipun menjengkelkan, bukanlah gotcha, karena ini adalah persyaratan yang konsisten di semua kode Go.)
ruakh
14

Jawaban atas pertanyaan itu cukup mudah. Bahasa apa pun yang memiliki "penyisipan titik koma otomatis" mungkin bermasalah di baris itu. Masalahnya dengan ini

return
{
     name: 'rajat'
};

..adalah mesin js akan memasukkan titik koma setelah return;pernyataan (dan oleh karena itu, kembali undefined). Contoh ini adalah alasan yang baik untuk membuka tanda kurung kurawal selalu di sisi kanan dan tidak pernah di sisi kiri juga. Karena Anda sudah memperhatikan dengan benar, jika ada tanda kurung kurawal di baris yang sama, penerjemah akan memperhatikan itu dan tidak bisa memasukkan titik koma.

jAndy
sumber
6

FWIW, JSLint melaporkan beberapa peringatan dengan sintaks tersebut:

$ jslint -stdin
function foo(){
  return
  { x: "y" };
}
^D
(3): lint warning: unexpected end of line; it is ambiguous whether these lines are part of the same statement
  return
........^

(3): lint warning: missing semicolon
  { x: "y" };
..^

(3): lint warning: unreachable code
  { x: "y" };
..^

(3): lint warning: meaningless block; curly braces have no impact
  { x: "y" };
..^

(3): lint warning: use of label
  { x: "y" };
.....^

(3): lint warning: missing semicolon
  { x: "y" };
...........^

(3): lint warning: empty statement or extra semicolon
  { x: "y" };
............^


0 error(s), 7 warning(s)
Brandan
sumber
1

Bahasa pertama di mana saya menemukan ini adalah awk (yang juga memiliki bagian sintaks "keanehan"; titik dua opsional, penggabungan string hanya menggunakan spasi dan seterusnya ...) Saya pikir para desainer DTrace, yang berdasarkan sintaks D secara longgar di awk, sudah cukup akal untuk TIDAK menyalin fitur ini, tetapi saya tidak dapat mengingatnya. Contoh sederhana (menghitung jumlah tag ENTITY di DTD, dari Mac saya):

$ cat printEntities.awk 
# This prints all lines where the string ENTITY occurs
/ENTITY/ {
  print $0
}
$ awk -f printEntities.awk < /usr/share/texinfo/texinfo.dtd | wc -l
     119

Jika skrip kecil ini malah ditulis dengan tanda kurung pada satu barisnya sendiri, inilah yang akan terjadi:

$ cat printAll.awk 
# Because of the brace placement, the print statement will be executed
# for all lines in the input file
# Lines containing the string ENTITY will be printed twice,
# because print is the default action, if no other action is specified
/ENTITY/
{ 
   print $0 
}
$ awk -f printAll.awk < /usr/share/texinfo/texinfo.dtd | wc -l
     603
$ /bin/cat < /usr/share/texinfo/texinfo.dtd | wc -l
     484
$ 
Anders S
sumber