Mengapa sebagian besar bahasa arus utama tidak mendukung sintaks “x <y <z” untuk perbandingan Boolean 3-arah?

34

Jika saya ingin membandingkan dua angka (atau entitas yang tertata dengan baik), saya akan melakukannya dengan x < y. Jika saya ingin membandingkan tiga dari mereka, siswa aljabar sekolah menengah akan menyarankan mencoba x < y < z. Programmer dalam diri saya kemudian akan menjawab dengan "tidak, itu tidak valid, Anda harus melakukan x < y && y < z".

Sebagian besar bahasa yang saya temui tampaknya tidak mendukung sintaks ini, yang aneh mengingat betapa umum itu dalam matematika. Python adalah pengecualian penting. JavaScript terlihat seperti pengecualian, tetapi sebenarnya hanya produk sampingan yang kurang menguntungkan dari operator yang didahulukan dan konversi tersirat; di node.js, 1 < 3 < 2dievaluasi menjadi true, karena itu benar-benar (1 < 3) < 2 === true < 2 === 1 < 2.

Jadi, pertanyaan saya adalah ini: Mengapa x < y < ztidak tersedia secara umum dalam bahasa pemrograman, dengan semantik yang diharapkan?

JesseTG
sumber
1
Inilah file tata bahasa, yang dengan mudah mereka tempel tepat di dokumentasi Python - Saya tidak berpikir itu sulit: docs.python.org/reference/grammar.html
Aaron Hall
Saya tidak tahu bahasa lain juga saya tahu Python, tapi saya bisa berbicara dengan kesederhanaan interpretasi Python tentang itu. Mungkin saya harus menjawab. Tapi saya tidak setuju dengan kesimpulan gnasher729 tentang hal itu melakukan kerusakan.
Aaron Hall
@ErikEidt - Permintaan dapat menulis ekspresi matematika seperti yang diajarkan di sekolah menengah (atau sebelumnya). Setiap orang yang memiliki kecenderungan matematis tahu apa arti $ a <b <c <d $. Hanya karena ada fitur tidak berarti Anda harus menggunakannya. Mereka yang tidak menyukainya selalu dapat membuat aturan pribadi atau proyek yang melarang penggunaannya.
David Hammen
2
Saya pikir apa yang terjadi adalah bahwa lebih baik bagi tim C # (sebagai contoh) untuk mengeksplorasi LINQ dan di masa depan mungkin mencatat jenis dan pola yang cocok daripada menambahkan gula sintaksis yang akan menyelamatkan orang 4 penekanan tombol dan tidak benar-benar tambahkan ekspresi apa pun (Anda juga dapat menulis metode helpermet seperti static bool IsInRange<T>(this T candidate, T lower, T upper) where T : IComparable<T>jika itu benar-benar mengganggu Anda untuk melihatnya &&)
sara
1
SQL cukup "mainstream" dan Anda dapat menulis "x antara 1 dan 10"
JoelFan

Jawaban:

30

Ini adalah operator biner, yang ketika dirantai, secara normal dan alami menghasilkan pohon sintaksis abstrak seperti:

sintaksis abstrak normal untuk operator biner

Ketika dievaluasi (yang Anda lakukan dari daun ke atas), ini menghasilkan hasil boolean dari x < y, maka Anda mendapatkan kesalahan ketik yang coba dilakukan boolean < z. Agar x < y < zberfungsi seperti yang Anda diskusikan, Anda harus membuat case khusus di kompiler untuk menghasilkan pohon sintaksis seperti:

pohon sintaksis kasus khusus

Bukannya tidak mungkin melakukan ini. Jelas itu, tetapi menambahkan beberapa kompleksitas ke parser untuk kasus yang tidak terlalu sering muncul. Pada dasarnya Anda membuat simbol yang terkadang bertindak seperti operator biner dan kadang-kadang bertindak secara efektif seperti operator ternary, dengan semua implikasi penanganan kesalahan dan yang memerlukannya. Itu menambah banyak ruang untuk kesalahan yang tidak diinginkan oleh perancang bahasa jika memungkinkan.

Karl Bielefeldt
sumber
1
"maka Anda mendapatkan kesalahan ketik yang mencoba melakukan boolean <z" - tidak jika kompiler memungkinkan untuk chaining dengan mengevaluasi y di tempat untuk perbandingan z. "Itu menambah banyak ruang untuk masalah yang tidak diinginkan oleh perancang bahasa jika memungkinkan." Sebenarnya, Python tidak memiliki masalah dalam melakukan ini, dan logika untuk parsing terbatas pada fungsi tunggal: hg.python.org/cpython/file/tip/Python/ast.c#l1122 - tidak banyak ruang untuk melakukan sesuatu salah. "Kadang-kadang bertindak seperti operator biner dan kadang-kadang secara efektif bertindak seperti operator trinary," Dengan Python, seluruh rantai perbandingan adalah ternary.
Aaron Hall
2
Saya tidak pernah mengatakan itu tidak bisa dilakukan, hanya kerja ekstra dengan kompleksitas ekstra. Bahasa lain tidak perlu menulis setiap kode yang terpisah hanya untuk menangani operator perbandingan mereka. Anda mendapatkannya secara gratis dengan operator biner lainnya. Anda hanya perlu menentukan prioritas mereka.
Karl Bielefeldt
Ya, tapi ... ada yang sudah Operator Ternary tersedia dalam banyak bahasa?
JensG
1
@ JensG. Denotasi terner berarti dibutuhkan 3 argumen. Dalam konteks tautan Anda, ini adalah operator kondisi ternary. Rupanya "trinary" dalam istilah yang diciptakan untuk operator yang tampaknya mengambil 2 tetapi sebenarnya mengambil 3. Masalah utama saya dengan jawaban ini adalah sebagian besar FUD.
Aaron Hall
2
Saya salah satu downvoters pada jawaban yang diterima ini. (@JesseTG: Harap tidak menerima jawaban ini.) Pertanyaan ini membingungkan apa x<y<zartinya, atau yang lebih penting x<y<=z,. Jawaban ini diartikan x<y<zsebagai operator trinary. Persis bagaimana ekspresi matematika yang terdefinisi dengan baik ini seharusnya tidak diinterpretasikan. x<y<zbukan singkatan untuk (x<y)&&(y<z). Perbandingan individu masih bersifat biner.
David Hammen
37

Mengapa x < y < ztidak tersedia secara umum dalam bahasa pemrograman?

Dalam jawaban ini saya menyimpulkan itu

  • meskipun konstruk ini sepele untuk diterapkan dalam tata bahasa bahasa dan menciptakan nilai bagi pengguna bahasa,
  • alasan utama bahwa hal ini tidak ada dalam sebagian besar bahasa adalah karena kepentingannya relatif terhadap fitur-fitur lain dan keengganan badan pengatur bahasa untuk
    • mengecewakan pengguna dengan kemungkinan melanggar perubahan
    • untuk pindah menerapkan fitur (yaitu: kemalasan).

pengantar

Saya bisa berbicara dari perspektif Pythonist tentang pertanyaan ini. Saya adalah pengguna bahasa dengan fitur ini dan saya suka mempelajari detail implementasi bahasa. Di luar ini, saya agak akrab dengan proses perubahan bahasa seperti C dan C ++ (standar ISO diatur oleh komite dan versi menurut tahun.) Dan saya telah menyaksikan Ruby dan Python mengimplementasikan perubahan yang melanggar.

Dokumentasi dan implementasi Python

Dari dokumen / tata bahasa, kami melihat bahwa kami dapat memadukan sejumlah ekspresi dengan operator pembanding:

comparison    ::=  or_expr ( comp_operator or_expr )*
comp_operator ::=  "<" | ">" | "==" | ">=" | "<=" | "!="
                   | "is" ["not"] | ["not"] "in"

dan dokumentasi selanjutnya menyatakan:

Perbandingan dapat dirantai secara sewenang-wenang, misalnya, x <y <= z setara dengan x <y dan y <= z, kecuali bahwa y dievaluasi hanya sekali (tetapi dalam kedua kasus z tidak dievaluasi sama sekali ketika x <y ditemukan menjadi salah).

Kesetaraan logis

Begitu

result = (x < y <= z)

secara logis setara dalam hal evaluasi x, ydan z, dengan pengecualian yang ydievaluasi dua kali:

x_lessthan_y = (x < y)
if x_lessthan_y:       # z is evaluated contingent on x < y being True
    y_lessthan_z = (y <= z)
    result = y_lessthan_z
else:
    result = x_lessthan_y

Sekali lagi, perbedaannya adalah bahwa y hanya dievaluasi satu kali dengan (x < y <= z) .

(Catatan, tanda kurung sama sekali tidak perlu dan mubazir, tetapi saya menggunakannya untuk kepentingan yang berasal dari bahasa lain, dan kode di atas adalah Python yang cukup legal.)

Memeriksa Pohon Sintaks Abstrak yang diuraikan

Kita dapat memeriksa bagaimana Python mem-parsing operator perbandingan:

>>> import ast
>>> node_obj = ast.parse('"foo" < "bar" <= "baz"')
>>> ast.dump(node_obj)
"Module(body=[Expr(value=Compare(left=Str(s='foo'), ops=[Lt(), LtE()],
 comparators=[Str(s='bar'), Str(s='baz')]))])"

Jadi kita dapat melihat bahwa ini sebenarnya tidak sulit untuk Python atau bahasa lain untuk diuraikan.

>>> ast.dump(node_obj, annotate_fields=False)
"Module([Expr(Compare(Str('foo'), [Lt(), LtE()], [Str('bar'), Str('baz')]))])"
>>> ast.dump(ast.parse("'foo' < 'bar' <= 'baz' >= 'quux'"), annotate_fields=False)
"Module([Expr(Compare(Str('foo'), [Lt(), LtE(), GtE()], [Str('bar'), Str('baz'), Str('quux')]))])"

Dan bertentangan dengan jawaban yang diterima saat ini, operasi ternary adalah operasi perbandingan generik, yang mengambil ekspresi pertama, iterable dari perbandingan spesifik dan iterable dari node ekspresi untuk mengevaluasi yang diperlukan. Sederhana.

Kesimpulan tentang Python

Saya pribadi menemukan bahwa semantik jangkauannya cukup elegan, dan sebagian besar profesional Python yang saya kenal akan mendorong penggunaan fitur ini, alih-alih menganggapnya merusak - semantiknya dinyatakan dengan jelas dalam dokumentasi terkenal (seperti disebutkan di atas).

Perhatikan bahwa kode lebih banyak dibaca daripada yang tertulis. Perubahan yang meningkatkan keterbacaan kode harus dianut, tidak diabaikan dengan meningkatkan momok umum Ketakutan, Ketidakpastian, dan Keraguan .

Jadi mengapa x <y <z tidak umum tersedia dalam bahasa pemrograman?

Saya pikir ada pertemuan alasan yang berpusat di sekitar kepentingan relatif fitur dan momentum relatif / kelembaman perubahan yang diizinkan oleh para gubernur bahasa.

Pertanyaan serupa dapat ditanyakan tentang fitur bahasa lain yang lebih penting

Mengapa pewarisan berganda tidak tersedia di Java atau C #? Tidak ada jawaban yang baik untuk pertanyaan ini . Mungkin para pengembang terlalu malas, sebagaimana ditegaskan Bob Martin, dan alasan yang diberikan hanyalah alasan. Dan multiple inheritance adalah topik yang cukup besar dalam ilmu komputer. Ini tentu saja lebih penting daripada perangkaian operator.

Ada solusi sederhana

Chaining operator pembanding adalah elegan, tetapi sama sekali tidak sepenting warisan ganda. Dan seperti halnya Java dan C # memiliki antarmuka sebagai solusi, demikian juga setiap bahasa untuk beberapa perbandingan - Anda cukup mengaitkan perbandingan dengan boolean "dan" s, yang bekerja dengan cukup mudah.

Sebagian besar bahasa diatur oleh komite

Sebagian besar bahasa berevolusi oleh komite (daripada memiliki Diktator Kebajikan Sejati yang masuk akal seperti yang dimiliki Python). Dan saya berspekulasi bahwa masalah ini hanya belum melihat cukup dukungan untuk keluar dari komite masing-masing.

Bisakah bahasa yang tidak menawarkan fitur ini berubah?

Jika suatu bahasa memungkinkan x < y < ztanpa semantik matematika yang diharapkan, ini akan menjadi perubahan besar. Jika tidak mengizinkannya di tempat pertama, itu akan hampir sepele untuk ditambahkan.

Memecah perubahan

Mengenai bahasa dengan perubahan yang rusak: kami memperbarui bahasa dengan mengubah perubahan perilaku - tetapi pengguna cenderung tidak menyukai ini, terutama pengguna fitur yang mungkin rusak. Jika seorang pengguna mengandalkan perilaku sebelumnya x < y < z, mereka kemungkinan besar akan protes keras. Dan karena sebagian besar bahasa diatur oleh komite, saya ragu kita akan mendapatkan banyak kemauan politik untuk mendukung perubahan semacam itu.

Aaron Hall
sumber
Jujur, saya tidak mengambil masalah dengan semantik yang disediakan oleh bahasa yang operasi rantai perbandingan seperti `x <y <z` tetapi sepele bagi pengembang untuk mental peta x < y < zuntuk (x < y) && (y < z). Memilih nits, model mental untuk perbandingan dirantai adalah matematika umum. Perbandingan klasik bukanlah matematika secara umum, tetapi logika Boolean. x < ymenghasilkan jawaban biner {0}. y < zmenghasilkan jawaban biner {1}. {0} && {1}menghasilkan jawaban deskriptif. Logikanya tersusun, tidak dirantai secara naif.
K. Alan Bates
Untuk berkomunikasi yang lebih baik, saya telah menyiapkan jawaban dengan satu kalimat yang secara langsung merangkum seluruh konten. Itu kalimat yang panjang, jadi saya hancurkan dalam peluru.
Aaron Hall
2
Alasan utama beberapa bahasa menerapkan fitur ini adalah bahwa sebelum Guido, tidak ada yang pernah memikirkannya. Bahasa yang mewarisi dari C tidak bisa mendapatkan "benar" ini (benar secara matematis) sekarang terutama karena pengembang C mendapatkannya "salah" (salah secara matematis) lebih dari 40 tahun yang lalu. Ada banyak kode di luar sana yang tergantung pada sifat berlawanan dengan intuisi bagaimana bahasa-bahasa itu ditafsirkan x<y<z. Suatu bahasa pernah memiliki kesempatan untuk mendapatkan sesuatu seperti ini dengan benar, dan satu peluang itu adalah pada saat permulaan bahasa tersebut.
David Hammen
1
@ K.AlanBates Anda membuat 2 poin: 1) rantai operator ceroboh dan 2) bahwa gula sintaksis tidak memiliki nilai. Yang pertama: Saya sudah menunjukkan bahwa chaining operator adalah 100% deterministik, bukan? Mungkin beberapa programmer terlalu malas secara mental untuk memperluas kemampuan mereka untuk memahami konstruksi? Untuk poin kedua: Kedengarannya bagi saya seperti Anda secara langsung berdebat tentang keterbacaan? Bukankah gula sintaksis biasanya dianggap sebagai hal yang baik ketika itu meningkatkan keterbacaan? Jika berpikir seperti ini adalah hal yang normal, mengapa seorang programmer tidak mau berkomunikasi seperti itu? Kode harus ditulis untuk dibaca, bukan?
Aaron Hall
2
I have watched both Ruby and Python implement breaking changes.Bagi mereka yang ingin tahu, berikut adalah perubahan melanggar di C # 5.0 yang melibatkan variabel lingkaran dan penutupan: blogs.msdn.microsoft.com/ericlippert/2009/11/12/...
user2023861
13

Bahasa komputer mencoba untuk mendefinisikan unit terkecil yang mungkin dan membiarkan Anda menggabungkannya. Unit terkecil yang mungkin adalah sesuatu seperti "x <y" yang memberikan hasil boolean.

Anda dapat meminta operator ternary. Contohnya adalah x <y <z. Sekarang kombinasi operator apa yang kami izinkan? Jelas x> y> z atau x> = y> = z atau x> y> = z atau mungkin x == y == z harus diizinkan. Bagaimana dengan x <y> z? x! = y! = z? Apa arti yang terakhir, x! = Y dan y! = Z atau ketiganya berbeda?

Sekarang promosi argumen: Di C atau C ++, argumen akan dipromosikan ke tipe umum. Jadi, apa artinya x <y <z dari x adalah ganda tetapi y dan z adalah int panjang? Ketiganya dipromosikan menjadi dua kali lipat? Atau y diambil dua kali dan selama di waktu yang lain? Apa yang terjadi jika dalam C ++ satu atau kedua operator kelebihan beban?

Dan terakhir, apakah Anda mengizinkan sejumlah operan? Seperti a <b> c <d> e <f> g?

Nah, itu semua menjadi sangat rumit. Sekarang apa yang saya tidak keberatan adalah x <y <z menghasilkan kesalahan sintaksis. Karena kegunaannya kecil dibandingkan dengan kerusakan yang dilakukan untuk pemula yang tidak tahu apa yang sebenarnya x <y <z lakukan.

gnasher729
sumber
4
Jadi, singkatnya, itu hanya fitur yang sulit untuk dirancang dengan baik.
Jon Purdy
2
Ini bukan alasan untuk menjelaskan mengapa tidak ada bahasa yang diketahui mengandung fitur ini. Sebenarnya, cukup mudah untuk memasukkannya ke dalam bahasa dengan cara yang jelas. Ini hanya masalah melihatnya sebagai daftar yang dihubungkan oleh operator dengan tipe yang sama dan bukannya setiap operator menjadi biner. Hal yang sama dapat dilakukan untuk jumlah x + y + z, dengan satu-satunya perbedaan yang tidak menyiratkan perbedaan semantik. Jadi hanya saja tidak ada bahasa terkenal yang pernah peduli untuk melakukannya.
cmaster
1
Saya pikir dalam Python ini sedikit optimasi, ( x < y < zsetara dengan ((x < y) and (y < z))tetapi yhanya dievaluasi sekali ) yang saya bayangkan bahasa yang dikompilasi mengoptimalkan jalan mereka. "Karena kegunaannya kecil dibandingkan dengan kerusakan yang dilakukan untuk pemula yang tidak tahu apa yang sebenarnya <<y <z lakukan." Saya pikir ini sangat berguna. Mungkin akan -1 untuk itu ...
Aaron Hall
Jika tujuan seseorang adalah merancang bahasa yang menghilangkan semua hal yang mungkin membingungkan bagi programmer yang paling bodoh, bahasa seperti itu sudah ada: COBOL. Saya lebih suka menggunakan python, sendiri, di mana orang memang bisa menulis a < b > c < d > e < f > g, dengan makna "jelas" (a < b) and (b > c) and (c < d) and (d > e) and (e < f) and (f > g). Hanya karena Anda dapat menulis bukan berarti Anda harus menulis. Menghilangkan keburukan semacam itu adalah bidang tinjauan kode. Di sisi lain, menulis 0 < x < 8dengan python memiliki arti yang jelas (tanpa tanda kutip) yang berarti bahwa x terletak antara 0 dan 8, eksklusif.
David Hammen
@ Davidvidammen, ironisnya, COBOL memang memungkinkan <b <c
JoelFan
10

Dalam banyak bahasa pemrograman, x < yadalah ekspresi biner yang menerima dua operan dan mengevaluasi ke hasil boolean tunggal. Oleh karena itu, jika perangkaian banyak ekspresi, true < zdan false < ztidak masuk akal, dan jika ekspresi tersebut berhasil dievaluasi, mereka cenderung menghasilkan hasil yang salah.

Jauh lebih mudah untuk dianggap x < ysebagai pemanggilan fungsi yang mengambil dua parameter dan menghasilkan hasil boolean tunggal. Bahkan, itulah berapa banyak bahasa yang mengimplementasikannya di bawah tenda. Ini komposable, mudah dikompilasi, dan hanya berfungsi.

The x < y < zSkenario jauh lebih rumit. Sekarang kompiler harus membuat tiga fungsi: x < y,, y < zdan hasil dari kedua nilai tersebut digabungkan bersama-sama, semua dalam konteks tata bahasa yang bisa dibilang ambigu .

Mengapa mereka melakukannya dengan cara lain? Karena itu tata bahasa yang tidak ambigu, jauh lebih mudah diimplementasikan, dan jauh lebih mudah untuk diperbaiki.

Robert Harvey
sumber
2
Jika Anda merancang bahasa, Anda memiliki kesempatan untuk menjadikannya hasil yang tepat .
JesseTG
2
Tentu itu menjawab pertanyaan. Jika pertanyaannya adalah mengapa , jawabannya adalah "karena itulah yang dipilih oleh perancang bahasa." Jika Anda bisa mendapatkan jawaban yang lebih baik dari itu, lakukan saja. Perhatikan bahwa pada dasarnya Gnasher mengatakan hal yang persis sama pada paragraf pertama jawabannya .
Robert Harvey
3
Sekali lagi, Anda membelah rambut. Programmer cenderung melakukan itu. "Kamu mau membuang sampah?" "Tidak." "Apakah kamu akan mengambil sampah?" "Iya nih."
Robert Harvey
2
Saya juga mengikuti paragraf terakhir. Python mendukung perbandingan rantai, dan pengurainya adalah LL (1). Ini tidak selalu sulit untuk mendefinisikan dan mengimplementasikan semantik baik: Python hanya mengatakan itu e1 op1 e2 op2 e3 op3 ...setara dengan e1 op e2 and e2 op2 e3 and ...kecuali bahwa setiap ekspresi hanya dievaluasi satu kali. (BTW aturan sederhana ini memiliki efek samping yang membingungkan bahwa pernyataan seperti a == b is Truetidak lagi memiliki efek yang diinginkan.)
2
@RobertHarvey re:answerDi sinilah pikiran saya segera pergi juga untuk komentar saya pada pertanyaan utama. Saya tidak mempertimbangkan dukungan untuk x < y < zmenambahkan nilai spesifik ke semantik bahasa. (x < y) && (y < z)lebih didukung secara luas, lebih eksplisit, lebih ekspresif, lebih mudah dicerna ke dalam konstituennya, lebih mudah dikomposisikan, lebih logis, lebih mudah di refactored.
K. Alan Bates
6

Sebagian besar bahasa arus utama (setidaknya sebagian) berorientasi objek. Pada dasarnya, prinsip yang mendasari OO adalah bahwa objek mengirim pesan ke objek lain (atau diri mereka sendiri), dan penerima pesan itu memiliki kontrol penuh atas bagaimana menanggapi pesan itu.

Sekarang, mari kita lihat bagaimana kita mengimplementasikan sesuatu seperti

a < b < c

Kami dapat mengevaluasinya dengan ketat dari kiri ke kanan (asosiasi kiri):

a.__lt__(b).__lt__(c)

Tetapi sekarang kita memanggil __lt__hasil a.__lt__(b), yaitu a Boolean. Itu tidak masuk akal.

Mari kita coba asosiatif yang benar:

a.__lt__(b.__lt__(c))

Nah, itu juga tidak masuk akal. Sekarang, sudah a < (something that's a Boolean).

Oke, bagaimana kalau memperlakukannya sebagai gula sintaksis. Mari kita membuat rantai <perbandingan n mengirim pesan n-1-ary. Ini bisa berarti, kami mengirim pesan __lt__ke a, lewat, bdan csebagai argumen:

a.__lt__(b, c)

Oke, itu berhasil, tapi ada asimetri yang aneh di sini: aharus memutuskan apakah itu kurang b. Tetapi btidak bisa memutuskan apakah itu kurang dari c, sebaliknya keputusan itu juga dibuat oleh a.

Bagaimana dengan menafsirkannya sebagai pesan n-ary yang dikirim ke this?

this.__lt__(a, b, c)

Akhirnya! Ini bisa berhasil. Ini berarti, bagaimanapun, bahwa pemesanan objek tidak lagi menjadi properti dari objek (misalnya apakah akurang dari bitu bukan properti aatau bukan b) tetapi sebagai properti dari konteks (yaitu this).

Dari sudut pandang arus utama itu tampak aneh. Namun, misalnya di Haskell, itu normal. Mungkin ada beberapa implementasi berbeda dari Ordtypeclass, misalnya, dan apakah akurang atau tidak b, tergantung pada instance typeclass mana yang berada dalam ruang lingkup.

Tapi sebenarnya, tidak bahwa aneh sekali! Java ( Comparator) dan .NET ( IComparer) memiliki antarmuka yang memungkinkan Anda untuk menyuntikkan relasi pemesanan Anda sendiri ke dalam misalnya algoritma penyortiran. Dengan demikian, mereka sepenuhnya mengakui bahwa pemesanan bukanlah sesuatu yang ditetapkan untuk suatu tipe melainkan tergantung pada konteks.

Sejauh yang saya tahu, saat ini tidak ada bahasa yang melakukan terjemahan seperti itu. Namun, ada satu yang lebih diutamakan: Ioke dan Seph memiliki apa yang oleh perancang mereka sebut "operator trinary" - operator yang secara biner sintaksis , tetapi terner semantik . Khususnya,

a = b

adalah tidak ditafsirkan sebagai mengirimkan pesan =ke alewat bsebagai argumen, melainkan sebagai mengirimkan pesan =ke "tanah saat ini" (konsep serupa tetapi tidak identik dengan this) lewat adan bsebagai argumen. Jadi, a = bdiartikan sebagai

=(a, b)

dan tidak

a =(b)

Ini dengan mudah dapat digeneralisasi ke operator n-ary.

Perhatikan bahwa ini sangat aneh untuk bahasa OO. Dalam OO, kami selalu memiliki satu objek tunggal yang pada akhirnya bertanggung jawab untuk menafsirkan pengiriman pesan, dan seperti yang telah kita lihat, tidak segera jelas untuk sesuatu seperti a < b < cobjek mana yang seharusnya.

Ini tidak berlaku untuk bahasa prosedural atau fungsional. Misalnya, dalam Skema , Common Lisp , dan Clojure , <fungsinya adalah n-ary, dan dapat dipanggil dengan sejumlah argumen arbitrer.

Secara khusus, <tidak tidak berarti "kurang dari", bukan fungsi-fungsi ini ditafsirkan sedikit berbeda:

(<  a b c d) ; the sequence a, b, c, d is monotonically increasing
(>  a b c d) ; the sequence a, b, c, d is monotonically decreasing
(<= a b c d) ; the sequence a, b, c, d is monotonically non-decreasing
(>= a b c d) ; the sequence a, b, c, d is monotonically non-increasing
Jörg W Mittag
sumber
3

Itu hanya karena perancang bahasa tidak memikirkannya atau tidak menganggap itu ide yang bagus. Python melakukannya seperti yang Anda gambarkan dengan tata bahasa LL (1) sederhana (hampir).

Neil G
sumber
1
Ini masih akan diuraikan dengan tata bahasa normal di hampir semua bahasa utama; itu tidak akan dipahami dengan benar karena alasan yang diberikan @RobertHarvey.
Mason Wheeler
@MasonWheeler Tidak, tidak harus. Jika aturan ditulis sehingga perbandingan dapat dipertukarkan dengan operator lain (katakanlah, karena mereka memiliki prioritas yang sama), maka Anda tidak akan mendapatkan perilaku yang benar. Fakta bahwa Python menempatkan semua perbandingan pada satu level adalah apa yang memungkinkannya untuk memperlakukan urutan sebagai konjungsi.
Neil G
1
Tidak juga. Masukkan 1 < 2 < 3ke dalam Java atau C # dan Anda tidak memiliki masalah dengan prioritas operator; Anda memiliki masalah dengan jenis yang tidak valid. Masalahnya adalah ini masih akan diuraikan persis seperti yang Anda tulis, tetapi Anda perlu logika kasus khusus di kompiler untuk mengubahnya dari urutan perbandingan individual ke perbandingan berantai.
Mason Wheeler
2
@MasonWheeler Yang saya katakan adalah bahasanya harus dirancang agar bisa berfungsi. Salah satu bagiannya adalah memperbaiki tata bahasa. (Jika aturan ditulis sehingga perbandingan dapat dipertukarkan dengan operator lain, katakanlah, karena mereka memiliki prioritas yang sama, maka Anda tidak akan mendapatkan perilaku yang benar.) Bagian lain dari itu adalah menafsirkan AST sebagai konjungsi, yang C ++ tidak bisa. Poin utama dari jawaban saya adalah bahwa itu adalah keputusan perancang bahasa.
Neil G
@MasonWheeler Saya pikir kami setuju. Saya hanya menyoroti bahwa tidak sulit untuk mendapatkan tata bahasa yang tepat untuk ini. Hanya masalah memutuskan terlebih dahulu bahwa Anda ingin itu bekerja dengan cara ini.
Neil G
2

Program C ++ berikut mengkompilasi dengan mengintip dari dentang, bahkan dengan peringatan yang diatur ke tingkat setinggi mungkin ( -Weverything):

#include <iostream>
int main () { std::cout << (1 < 3 < 2) << '\n'; }

Suite compiler gnu di sisi lain dengan baik memperingatkan saya itu comparisons like 'X<=Y<=Z' do not have their mathematical meaning [-Wparentheses].

Jadi, pertanyaan saya adalah ini: mengapa x <y <z tidak umum tersedia dalam bahasa pemrograman, dengan semantik yang diharapkan?

Jawabannya sederhana: Kompatibilitas mundur. Ada sejumlah besar kode di alam bebas yang menggunakan yang setara 1<3<2dan berharap hasilnya benar.

Perancang bahasa hanya memiliki satu kesempatan untuk mendapatkan "hak" ini, dan itulah titik waktu bahasa pertama kali dirancang. Melakukannya "salah" pada awalnya berarti programmer lain akan lebih cepat mengambil keuntungan dari perilaku "salah" itu. Melakukannya dengan "benar" untuk yang kedua kalinya akan merusak basis kode yang ada.

David Hammen
sumber
+1 karena program ini menghasilkan '1' sebagai hasil dari ekspresi yang jelas salah dalam matematika. Meskipun dibuat-buat, contoh dunia nyata dengan nama variabel yang tidak dapat dipahami akan menjadi mimpi buruk debugging jika fitur bahasa ini ditambahkan.
Seth Battin
@SethBattin - Ini bukan mimpi buruk debugging di Python. Satu-satunya masalah dengan Python adalah if x == y is True : ..., Pendapat saya: Orang-orang yang menulis kode semacam itu layak mengalami penyiksaan yang luar biasa dan luar biasa yang (jika ia hidup sekarang) akan membuat Torquemada sendiri pingsan.
David Hammen