Mengapa (posisi <ukuran) merupakan pola yang lazim dalam kondisi?


9

Dalam pernyataan kondisi (IF) semua orang menggunakan (position < size), tapi mengapa?
Hanya konvensi atau ada alasan bagus untuk itu?

Ditemukan di alam liar:

if (pos < array.length) {
   // do some with array[pos];
}

Jarang ditemukan:

if (array.length > pos) {
   // do some with array[pos];
}

7
Satu kasus di mana saya tidak keberatan memiliki "variabel" di sebelah kanan adalah if (MIN <= x && x <= MAX). (Dalam beberapa bahasa ini dapat ditulis sebagai MIN <= x <= MAX; dalam C, itu sah tetapi tidak berarti apa yang Anda pikirkan artinya).
Keith Thompson


5
Mungkin terkait dengan bagaimana interval ditulis [min, max]dan tidak [max, min]. Oleh karena itu, wajar untuk memeriksa daripada elemen xmilik interval dengan menulis min <= x <= max.
Andres F.

Sungguh sebuah teka-teki.
Tulains Córdova

Contoh kedua dapat diklarifikasi lebih lanjut seolah-olah (! (Array.lengh <= pos)) ...
OldFart

Jawaban:


48

Pola yang lebih dalam adalah bahwa kita secara alami menggunakan "[hal yang bervariasi] [perbandingan] [hal yang tidak bervariasi]" sebagai urutan standar. Prinsip ini berlaku untuk contoh Anda karena posisi dapat bervariasi, sementara ukurannya tidak.

Satu-satunya pengecualian umum adalah ketika menguji kesetaraan beberapa programmer melatih diri mereka sendiri untuk menggunakan urutan yang berlawanan (dikenal sebagai kondisi Yoda ) untuk menghindari kesamaan variable = constantdaripada variable == constantbug - Saya tidak tahan dengan ide ini karena saya menemukan urutan alami dijelaskan di atas jauh lebih mudah dibaca, terutama karena itulah cara kami mengekspresikan ide dalam bahasa Inggris, dan karena kebanyakan kompiler modern akan mendeteksi ini dan mengeluarkan peringatan.


3
Bergantung pada alat pengembangan Anda, banyak juga akan memperingatkan (atau kesalahan) pada variable = constantkonstruksi.
GalacticCowboy

5
+1. Cari "Kondisi Yoda" untuk detail lebih lanjut tentang constant == variablefenomena tersebut.
John M Gant

Saya telah melihat hal yang sama baru-baru ini di basis kode saya sendiri (misalnya if(DBNull == row["fieldName"]) methodCall()dan bertanya-tanya apakah saya menjadi gila karena sebagian besar waktu saya melihatnya melakukan sebaliknya)
Andrew Grey

1
Saya juga akan menambahkan yang (position < size)sering menyatakan batas atas, sehingga efeknya menyatakan kembali bagian lowerbound <= position < upperbound, dengan ukuran sebagai bagian atas. Dengan dua kendala eksplisit, positionhanya bisa berjalan di tengah.
Steve314

4
Mungkin terkait dengan bahasa; kita mengurai " Operator X Y " sebagai " X adalah ( Operator Y )", seperti relasi adalah sifat dari X . Dengan menanyakan perbandingan, kami bertanya apakah X memiliki nilai baik atau buruk (dan Y diperlakukan secara lokal sebagai konstanta). Bertanya "pos <array.length" terasa seperti bertanya: "Apakah posisinya oke (lebih kecil dari panjang array)?" Jika tidak, ada sesuatu yang salah tentang posisi itu; beri saya posisi lain, dan saya akan senang melakukan apa yang Anda inginkan. Tapi tidak ada yang salah tentang panjang array. Meminta "array.length> pos" terasa seperti kita harus menambah array jika terlalu pendek.

14

Satu-satunya pembenaran yang pernah saya lihat untuk itu adalah seperti garis angka atau hal-hal lain yang kami pelajari di sekolah. Sebagai contoh, kami menulis baris angka seperti ini:

<--|--|--|--|--|--|-->
   1  2  3  4  5  6

Hal-hal kecil muncul di sebelah kiri hal-hal yang lebih besar. Hal yang sama berlaku untuk hal-hal lain seperti tanggal (pikirkan bagaimana kalender disusun).

Ini pada dasarnya bermuara pada bagaimana kita secara alami memikirkan urutan berbagai hal. Lebih mudah untuk membaca formulir pertama karena Anda tidak perlu melakukan banyak proses mental di dalamnya.


1
Maksud Anda ungkapan yang mengevaluasi nilai yang lebih kecil lebih dulu dalam kondisi tersebut? Bagaimana Anda bisa yakin itu benar jika nilai mengubah runtime?
Tulains Córdova

@ user61852 Anda tidak perlu tahu apa nilainya saat runtime. Mis: Saya punya 2 nilai yang saya hitung pada runtime valueA dan valueB dan saya ingin menguji bahwa valueA lebih kecil dari valueB. Saya akan menulis "jika (valueA <valueB)". Apakah valueA akhirnya lebih kecil dari valueB tidak penting. Lebih mudah (setidaknya bagi saya) untuk melihat itu dan tahu bahwa saya mencari ketika valueA lebih kecil dari valueB. Jika saya melihat "jika (valueB> valueA)" saya harus berhenti dan memikirkan hal mana yang lebih kecil ketika saya akan mengikuti cabang kode ini.
Becuzz

1
Saya salah paham. Saya memilih jawabannya. Sekarang saya ingin memilihnya, tetapi situs menuntut jawaban untuk diedit sehingga saya dapat mengubah suara saya. Harap lakukan beberapa pengeditan agar saya dapat memilihnya.
Tulains Córdova

@ user61852 Anda harus dapat mengubah suara Anda sekarang.
Becuzz

11

Sementara itu terutama masalah konvensi, menurut pendapat saya ini paling cocok dengan cara kita berpikir - itu menunjukkan item yang kita tempatkan penekanan.

Jika kita menerjemahkan ini ke bahasa Inggris, itu akan menjadi frasa "Jika posisinya kurang dari panjang array", di mana subjek kalimat adalah item sementara.

Untuk menyatakannya dengan cara lain, "jika panjang array lebih besar dari posisi" menempatkan panjang array (diasumsikan sebagai nilai tetap) dalam subjek dan posisi (transient) menjadi objek langsung.


3
Sebenarnya (dalam kalimat terakhir Anda) posisi menjadi objek preposisi. Tapi saya setuju dengan apa yang ingin Anda katakan. Dalam linguistik kita akan mengatakan bahwa posisi adalah topik , dan "kurang dari panjang array" adalah komentar . "Kecenderungan untuk menempatkan konstituen yang di-kalimat-kan pada awalnya - topik (fronting topik) tersebar luas." en.wikipedia.org/wiki/…
LarsH

4

Pendapat saya, dan ini hanya pendapat saya, adalah bahwa itu adalah konvensi untuk keterbacaan. Meskipun keduanya identik, mereka terasa berbeda di otak saya. Saya tidak ingin tahu apakah ukuran array lebih besar dari pos. Saya ingin tahu apakah pos lebih kecil dari ukuran array.

Ini seperti diskusi setengah kosong vs setengah penuh. Secara matematis identik, tetapi otak saya akan melihatnya secara berbeda tergantung pada konteksnya.

Secara pribadi, jika saya melihat

if (array.lengh > pos) {
    // do some with array[pos];
}

Saya akan mulai berpikir tentang apakah itu bug dan apa yang dimaksud oleh programmer. Apakah dia mencoba melakukan sesuatu selain memeriksa batas?

Mungkin saya tidak cerdas, tetapi jika saya harus melakukan analisis semacam itu pada setiap baris kode, otak saya sakit.


3

Untuk mengungkapkan apa yang telah dicoba beberapa orang, dengan cara yang berbeda ...

Ketika tatanan tidak membuat perbedaan pada perilaku program, perbedaannya jelas masalah apa yang paling mudah dibaca oleh manusia. Inilah alasan linguistik mengapa menempatkan "topik" di sebelah kiri masuk akal:

Dalam linguistik, topik kalimat adalah apa yang dibicarakan, dan komentar adalah apa yang dikatakan tentang topik tersebut. Dalam contoh ini, kita dapat berasumsi bahwa itu positionadalah topik , dan "kurang dari panjang array" adalah komentar . Dalam bahasa Inggris, dan dalam banyak bahasa lain, topik biasanya diungkapkan sebelum komentar.
" Kecenderungan untuk menempatkan konstituen yang diartikan sebagai kalimat-pada awalnya (topik fronting) tersebar luas. "

Jadi aturan praktis yang baik adalah untuk memikirkan baris Anda kode sebagai kalimat (atau klausa, dalam hal ini), memutuskan apa kalimat tersebut sekitar , dan meletakkan yang pertama jika Anda bisa. Seringkali, apa kalimat "tentang" akan menjadi variabel daripada konstanta. Tetapi kadang-kadang komentar juga akan melibatkan variabel, jadi Anda tidak bisa pergi begitu saja.


1

Ini adalah kombinasi dari dua hal, keduanya berasal dari assembler yang mendasari bahwa bahasa awal dikompilasi (dan banyak yang saat ini juga).

  1. Array adalah offset berbasis-nol dalam memori (yaitu potongan data pertama pada awal blok memori yang dialokasikan ... indeks-0). Oleh karena itu penggunaan 0..n-1 untuk bagian yang bervariasi.

  2. Bercabang jika nilainya kurang dari nilai yang lain (atau mendaftar, dll) biasanya merupakan satu instruksi. Oleh karena itu penggunaan operator yang kurang dari (<) sederhana.

Jadi, polanya pindah dari assembler lama ke ANSI-C (yang lebih mirip assembler makro dalam beberapa hal) dan dari sana ke Jawa dan bahasa mirip-C lainnya.


0

Seperti banyak jawaban lain katakan, seringkali lebih mudah dibaca:

[thing that varies] [comparison] [thing that does not vary]

Hampir semua orang yang saya kenal menggunakan gaya ini secara eksklusif.

Ada satu pengecualian, untuk bahasa gaya-C yang digunakan =untuk penugasan dan ==untuk perbandingan. Jika Anda tidak sengaja mengetik:

if (variable = 5) ...

dari pada:

if (variable == 5) ...

maka Anda tidak akan mendapatkan kesalahan karena ini adalah baris kode yang valid. (Beberapa kompiler dan IDE akan memperingatkan Anda tentang melakukan ini, tetapi masih sangat mudah untuk salah ketik seperti itu.)

Namun, jika Anda menulis:

if (5 == variable) ...

compiler / interpreter akan error karena itu bukan konstruk yang valid (dalam kebanyakan bahasa, toh).

Pergantian ini sering disebut Kondisi Yoda .

UPDATE : Berikut adalah daftar tempat di mana Ketentuan Yoda berguna .


-1

Secara pribadi, saya lebih suka ini:

bool positionIsWithinBounds = pos < array.length;
if (positionIsWithinBounds) {
   // do some with array[pos];
}

... lebih banyak kode, tetapi juga sangat mudah dibaca.


4
+1 untuk memberi nama perbandingan. Sungguh, saya suka pendekatan ini lebih baik untuk persyaratan yang lebih kompleks, dan tidak begitu banyak untuk kasus-kasus sederhana seperti ini. Ini benar-benar membuat saya berhenti untuk berpikir tentang "array", "batas", "dalam", dan apa artinya semua itu, ketika secara naluriah saya tahu apa artinya posmenjadi > array.length. Dengan kata lain, meskipun itu membuat arti dari conditional sangat jelas, itu sebenarnya membuat sedikit lebih sulit untuk membaca IMO.
John M Gant

Namun nama lain untuk melacak ...
Deduplicator

-1

Ini masalah preferensi atau konvensi. Jika Anda ingin konsisten, ada dua cara yang masuk akal untuk melakukannya:

  1. Selalu letakkan "subjek" terlebih dahulu (anggap sebagai kalimat) - nilai ujiannya. Jadi misalnya Anda akan menulisif (age>5)

  2. Atau selalu menempatkan elemen yang lebih kecil terlebih dahulu (anggap sebagai nilai-nilai yang dipesan pada layar Anda dalam urutan alami). Jadi misalnya Anda akan menulis if (a<b)terlepas dari apakah kode ini sebagian besar tentang a atau sebagian besar tentang b.

Kedua konvensi akan merekomendasikan cuplikan pertama yang Anda perlihatkan alih-alih yang kedua, jadi saya kira dalam kasus khusus ini Anda memiliki jawaban. Saya akan mengatakan itu bijaksana untuk menghindari menulis kode yang melanggar (1) dan (2) di sini, karena akan membuat lebih sulit untuk dibaca oleh kebanyakan orang.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.