Pertimbangkan yang berikut ini:
if(a == b or c)
Dalam sebagian besar bahasa, ini perlu ditulis sebagai:
if(a == b or a == c)
yang sedikit rumit dan mengulang informasi.
Saya tahu sintaks sampel saya di atas agak kikuk, tetapi saya yakin ada cara yang lebih baik untuk menyampaikan gagasan itu.
Mengapa tidak banyak bahasa yang menawarkannya? Apakah ada masalah kinerja atau sintaksis?
a == b or c
, dan bahkan tidak IMHOsebelum IMHO.Jawaban:
Masalah sintaks adalah - bahwa itu memerlukan sintaks.
Apa pun sintaksis bahasa Anda, orang yang menggunakan bahasa harus mempelajarinya. Kalau tidak, mereka berisiko melihat kode dan tidak tahu apa fungsinya. Jadi itu umumnya dianggap hal yang baik jika bahasa memiliki sintaksis sederhana yang menangani banyak kasus.
Dalam contoh spesifik Anda, Anda mencoba mengambil operator infiks (fungsi yang mengambil dua argumen tetapi ditulis
Argument1 Operator Argument2
) dan mencoba memperluasnya ke beberapa argumen. Itu tidak bekerja dengan sangat bersih karena seluruh titik operator infiks, sejauh ada satu, adalah untuk menempatkan operator tepat di antara 2 argumen. Memperluas ke(Argument1 Operator Argument2 MagicallyClearSymbol Argument3...)
tampaknya tidak menambah banyak kejelasanEquals(Arg1,Arg2,...)
. Infix juga biasanya digunakan untuk meniru konvensi matematika yang sudah dikenal banyak orang, yang tidak akan berlaku untuk sintaks alternatif.Tidak akan ada masalah kinerja tertentu yang terkait dengan ide Anda, selain itu parser harus berurusan dengan tata bahasa dengan satu atau dua aturan produksi, yang mungkin memiliki sedikit efek pada kecepatan parsing. Ini mungkin membuat beberapa perbedaan untuk bahasa yang dikompilasi ditafsirkan atau JIT, tetapi mungkin tidak perbedaan besar.
Masalah yang lebih besar dengan idenya adalah bahwa membuat banyak kasus khusus dalam suatu bahasa cenderung merupakan ide yang buruk .
sumber
.
. Jadi mereka ditulis sebagaiarg1 op (arg2, arg3)
. Tidak persis cantik, tetapi dibutuhkan di beberapa tempat dalam konteks bahasa itu.if my_var in (a, b)
itu? bukankah ini lebih merupakan pertanyaan menggunakan alat yang tepat untuk pekerjaan itu?a == b or c
sementara yang lain inginkana == b or c but not d
. IMO di situlah fungsi utilitas / perpustakaan datang untuk menyelamatkan.f().Equals(a,b,c)
; dapat dievaluasi karena(var temp=f(); temp.Equals(a)||temp.Equals(b)||temp.Equals(c))
sintaksinya akan sempurna, tetapi jika itu dievaluasi karenaint[] arr = {a,b,c}; f().Equals(arr);
itu tidak akan begitu baik, terutama jika array baru harus dibuat untuk setiap panggilan.Karena ini bukan masalah, dan menyelesaikannya pada dasarnya memberikan manfaat nol, tetapi menerapkannya akan menghasilkan biaya yang tidak nol.
Fungsi berbasis rentang yang ada dan sedemikian rupa sehingga hampir setiap bahasa memang menawarkan dapat bekerja dengan baik dalam situasi ini jika skala ke ukuran di mana
a == b || a == c
tidak akan memotongnya.sumber
in_array($a, [$b, $c, $d, $e, $f])
. : PBeberapa bahasa memang memiliki fitur seperti itu. Misalnya dalam Perl6 kita bisa menggunakan persimpangan , yang merupakan "superposisi" dari dua nilai:
Persimpangan memungkinkan kami untuk mengekspresikan operasi pada set data yang cukup ringkas, mirip dengan cara operasi skalar mendistribusikan koleksi dalam beberapa bahasa. Misalnya menggunakan Python dengan numpy, perbandingan dapat didistribusikan ke semua nilai:
Namun, ini hanya berfungsi untuk tipe primitif tertentu.
Mengapa persimpangan bermasalah? Karena operasi pada persimpangan mendistribusikan nilai-nilai yang terkandung, objek persimpangan itu sendiri berperilaku seperti proxy untuk pemanggilan metode - sesuatu yang bisa ditangani oleh beberapa jenis sistem selain dari pengetikan bebek.
Ketik masalah sistem dapat dihindari jika persimpangan seperti itu hanya diizinkan sebagai sintaks khusus di sekitar operator pembanding. Tetapi dalam kasus ini, mereka sangat terbatas sehingga mereka tidak menambah nilai yang cukup untuk ditambahkan ke bahasa yang waras. Perilaku yang sama dapat diekspresikan menggunakan operasi yang ditetapkan atau mengeja semua perbandingan secara manual, dan sebagian besar bahasa tidak percaya menambahkan sintaks yang berlebihan jika sudah ada solusi yang sangat bagus.
sumber
2 in [1, 2, 3]
. Di sisi lain, jika numpy memiliki.all()
atau sesuatu, python polos setara tidak hampir ringkas.==
operator, kami juga bisa menggunakan<
- di mana Andain
sekarang? Persimpangan lebih umum daripada yang ditetapkan tes keanggotaan, karena operasi pada persimpangan mendistribusikan ke semua anggota -(x|y).foo
adalahx.foo|y.foo
, sampai persimpangan akhirnya runtuh ke nilai tunggal. Kode NumPy yang disediakan menunjukkan terjemahan Pers6 yang persis sama tetapi lebih bertele-tele, dengan asumsi tipe primitif.Dalam bahasa dengan makro, mudah untuk menambahkan sesuatu seperti itu jika belum ada di sana. Pertimbangkan Racket
Dalam bahasa lain tanpa metaprogramming, mungkin Anda dapat memformulasikannya kembali sebagai set / daftar yang memeriksa keanggotaan:
sumber
Dalam beberapa bahasa (populer)
==
operator tidak transitif. Misalnya dalam JavaScript0
sama dengan keduanya''
dan'0'
, tetapi kemudian''
dan'0'
tidak sama dengan satu sama lain. Lebih banyak kebiasaan semacam itu di PHP.Ini berarti
a == b == c
akan menambah ambiguitas lain, karena dapat menghasilkan hasil yang berbeda tergantung pada apakah itu ditafsirkan sebagai(a == b) & (a == c)
atau(a == b) & (a == c) & (b == c)
.sumber
Dalam sebagian besar bahasa, ini seharusnya dapat dicapai secara sepele dengan menulis suatu
In
fungsi, jadi mengapa menjadikannya bagian dari bahasa aktual?Linq, misalnya, memiliki
Contains()
.Baiklah, untuk semua yang Anda ajak, inilah implementasi saya di C #:
sumber
a == b || a == c
berulang kali, mungkin inilah saatnyaequals_any(a, {b, c})
if (a > (b or c))
danif (a mod (b or c) == 2)
.i
variabel. Dan secara keseluruhan tampaknya ditulis setelah Anda memiliki hari yang panjang :) Karena meletakkan keduanyareturn true
danreturn false
di dalam loop di sini berarti tidak ada cara itu akan membuatnya melampaui iterasi pertama. Anda hanya membandingkan dengan yang pertamavalue
. Ngomong-ngomong, mengapa tidak menggunakanAny
seperti yang disarankan @Bob dan menyederhanakannya menjadireturn values.Any(value => Object.Equals(obj, value));
"if (a == b atau c)" berfungsi di sebagian besar bahasa: jika a == b atau jika c tidak negatif, nol, atau nol.
Mengeluh bahwa itu sangat tidak tepat: Anda tidak harus menumpuk selusin hal menjadi sebuah persyaratan. Jika Anda perlu membandingkan satu nilai dengan angka sembarang dari nilai lainnya, maka buat subrutin.
sumber
c
mengevaluasi ke boolean, maka hampir semua bahasa dapat menangania == b || c
:)if(a == b or c)
. Saya perlu istirahat, saya pikir ...: Pif (a == b or c)
adalah pseudo-code untuk memeriksa apakaha
sama denganb
, ataua
sama denganc
. Itu tidak dimaksudkan untuk memeriksa bahwac
itu bukan nol.Biasanya, Anda ingin mempertahankan sintaks Anda seminimal mungkin dan sebaliknya membiarkan konstruksi seperti itu didefinisikan dalam bahasa itu sendiri.
Misalnya, di Haskell Anda dapat mengubah fungsi apa pun dengan dua atau lebih argumen menjadi operator infiks menggunakan backtick. Ini memungkinkan Anda untuk menulis:
di mana
elem
hanya fungsi normal mengambil dua argumen - nilai dan daftar nilai - dan memeriksa apakah yang pertama adalah elemen yang kedua.Bagaimana jika Anda ingin menggunakan,
and
bukanor
? Di Haskell, Anda bisa menggunakan yang berikut daripada menunggu vendor kompiler menerapkan fitur baru:sumber
Beberapa bahasa menawarkan ini - sampai batas tertentu.
Mungkin bukan sebagai contoh spesifik Anda , tetapi ambil contoh garis Python:
Jadi, beberapa bahasa tidak masalah dengan beberapa perbandingan, selama Anda mengekspresikannya dengan benar.
Sayangnya, itu tidak berfungsi seperti yang Anda harapkan untuk perbandingan.
"Apa maksudmu mengembalikan True atau 4?" - Mempekerjakan setelah Anda
Salah satu solusi dalam hal ini, setidaknya dengan Python, adalah menggunakannya sedikit berbeda:
Sunting: Berikut ini juga akan melakukan sesuatu yang serupa, lagi dengan Python ...
Jadi, bahasa apa pun yang Anda gunakan, mungkin bukan karena Anda tidak bisa melakukannya, hanya saja Anda harus terlebih dahulu melihat lebih dekat bagaimana logika sebenarnya bekerja. Biasanya itu hanya masalah mengetahui apa yang sebenarnya Anda minta 'bahasa' untuk memberitahu Anda.
sumber
Metode indexOf, yang digunakan pada Array, yang dimiliki hampir semua bahasa, memungkinkan untuk membandingkan nilai dengan beberapa lainnya, jadi saya kira operator khusus tidak masuk akal.
Dalam javascript yang akan menulis:
sumber
Anda bertanya mengapa kita tidak bisa melakukan ini:
if(a == b or c)
Python melakukan ini dengan sangat efisien, pada kenyataannya, paling efisien dengan
set
:Untuk pengujian keanggotaan, 'set' memeriksa bahwa hash elemen adalah sama dan hanya kemudian membandingkan untuk kesetaraan, sehingga elemen, b dan c, harus dapat hashable, jika tidak daftar langsung membandingkan untuk kesetaraan:
sumber
Bahasa gaya APL memungkinkan Anda untuk membandingkan skalar dengan setiap elemen dalam vektor dalam satu operasi. Ini menghasilkan vektor Boolean. Sebagai contoh, saya ingin mempromosikan tanpa malu-malu apl kalkulator minimal saya, inca ( juru bahasa online ).
Untuk mengurangi ini menjadi nilai tunggal, kita dapat melakukan inklusif atau dengan menjumlahkan dan memeriksa bukan nol.
Jadi, seperti jawaban yang lain katakan, masalahnya adalah sintaksis. Hingga taraf tertentu, solusi sintaksis telah ditemukan, dengan biaya yang mahal untuk mempelajari paradigma array.
sumber