Pencocokan satu nilai terhadap banyak kemungkinan dapat ditulis dengan case/when tanpa merangkai if/elsif yang panjang. Topik ini membahas struktur dasar case/when, mekanisme operator === di balik pencocokannya, serta penggunaan rentang (range), kelas, dan regular expression (pola teks) di dalam when. Setelah membacanya, penggolongan nilai ke dalam banyak kategori dapat ditulis secara ringkas dan mudah diperluas.
Struktur dasar case/when#
Konstruksi case menerima satu nilai untuk dicocokkan, lalu setiap cabang when menyatakan satu atau lebih kemungkinan pembanding. Cabang pertama yang cocok dijalankan, dan cabang else menjadi jalur cadangan apabila tidak ada yang cocok. Beberapa kemungkinan dalam satu when ditulis dipisahkan koma, dan kecocokan terjadi apabila salah satu pembandingnya cocok.
hari = "Rabu"
case hari
when "Sabtu", "Minggu"
puts "Akhir pekan"
when "Senin"
puts "Awal pekan kerja"
else
puts "Hari kerja biasa"
endHari kerja biasaNilai Rabu tidak sama dengan kedua nama hari akhir pekan maupun Senin, sehingga cabang else yang dijalankan. Bentuk when "Sabtu", "Minggu" menampung dua kemungkinan dengan badan yang sama tanpa menulis cabang dua kali. Jumlah cabang boleh sebanyak yang diperlukan, dan pencocokan selalu berhenti pada kecocokan pertama.
Mekanisme operator ===#
Di balik setiap when, Ruby memanggil operator === dengan nilai milik case sebagai argumennya. Pada String dan Symbol, operator ini berperilaku sama seperti ==, yaitu memeriksa kesetaraan nilai. Kelas lain mendefinisikan arti tambahan yang membuat pencocokan menjadi lebih ekspresif, dan contoh berikut memanggil === pada rentang, kelas, serta pola Regexp secara langsung.
p((0..15) === 10)
p(Integer === 42)
p(/\AKT-\d{3}\z/ === "KT-104")true
true
trueMetode p menampilkan nilai ekspresi apa adanya, sehingga ketiga baris keluarannya berupa true. Rentang menjawab pertanyaan keanggotaan, kelas menjawab pertanyaan jenis, dan Regexp menjawab kecocokan pola terhadap string. Tabel berikut merangkum arti === untuk jenis pembanding yang paling sering digunakan di dalam when.
Pembanding di dalam when | Arti === |
|---|---|
Rentang 0..15 | Benar apabila nilai berada di dalam rentang, termasuk kedua batasnya |
Kelas Integer | Benar apabila nilai merupakan instans dari kelas tersebut |
Pola Regexp /\A...\z/ | Benar apabila nilai berupa string yang cocok dengan pola |
String dan Symbol | Benar apabila nilainya sama persis |
Pencocokan kelas#
Pembanding berupa kelas memanfaatkan arti === milik kelas, yaitu memeriksa apakah nilai merupakan instans dari kelas itu. Pemeriksaan jenis semacam ini menggantikan rangkaian nilai.is_a?(Integer) yang berulang. Contoh berikut menggolongkan isi array menurut kelasnya, dan urutan when menentukan hasil karena penilaian berhenti pada kecocokan pertama.
hasil = [82, "82", 82.0]
hasil.each do |nilai|
case nilai
when Integer then puts "#{nilai.inspect} bilangan bulat"
when Float then puts "#{nilai.inspect} bilangan desimal"
when String then puts "#{nilai.inspect} berupa teks"
end
end82 bilangan bulat
"82" berupa teks
82.0 bilangan desimalNilai 82.0 jatuh ke cabang Float karena Integer === 82.0 bernilai palsu, sekalipun angkanya tampak bulat. Pembedaan ketat ini sesuai dengan cara Ruby menyimpan jenis nilai. Apabila satu cabang perlu menampung lebih dari satu kelas, tuliskan kelas-kelas tersebut dipisahkan koma dalam satu when, misalnya when Integer, Float.
Rentang dan case sebagai ekspresi#
Pembanding berupa rentang membuat penggolongan berdasarkan ambang batas menjadi ringkas. Rentang pada when mencakup seluruh nilai tanpa lubang apabila rentang-rentangnya saling menyambung. Konstruksi case juga merupakan ekspresi, sehingga hasil cabang yang dijalankan dapat ditampung langsung ke dalam variabel.
# Kategori suhu sensor ruangan dengan case/when dan rentang.
suhu = 27
kategori =
case suhu
when 0..15 then "dingin"
when 16..25 then "sejuk"
when 26..32 then "nyaman"
when 33..40 then "hangat"
else "ekstrem"
end
puts "Suhu #{suhu} derajat tergolong #{kategori}"Suhu 27 derajat tergolong nyamanJalankan berkas di atas dengan perintah ruby kategori-suhu.rb. Suhu 27 jatuh pada rentang 26..32, sehingga variabel kategori berisi teks “nyaman” dan program menampilkan satu baris hasil. Tanpa cabang else, case yang tidak menemukan kecocokan tetap selesai tanpa pesan, dan variabel penampungnya berisi nil.
case tanpa nilai#
case boleh ditulis tanpa nilai sama sekali, dan setiap when berisi kondisi boolean yang dinilai sendiri-sendiri. Bentuk ini setara dengan if/elsif, tetapi susunannya lebih sejajar sehingga nyaman untuk daftar syarat yang panjang. Penggunaannya tepat apabila syaratnya berupa perbandingan yang berbeda-beda dan tidak berpijak pada satu nilai tunggal.
kelembapan = 71
case
when kelembapan < 40
puts "Udara kering"
when kelembapan < 70
puts "Udara normal"
else
puts "Udara lembap"
endUdara lembapKelembapan 71 melewati dua kondisi pertama dan jatuh ke cabang else, sehingga program melaporkan udara lembap. Kondisi kelembapan < 70 hanya dinilai apabila kondisi pertama palsu, sehingga batas bawahnya tidak perlu ditulis ulang menjadi kelembapan >= 40 && kelembapan < 70. Sifat berlapis ini sama dengan perilaku if/elsif karena keduanya dinilai dari atas ke bawah.
Ringkasan#
case/whenmencocokkan satu nilai terhadap pembanding pada setiap cabang, menjalankan yang pertama cocok, dan menggunakanelsesebagai cadangan.- Pencocokan memanggil
===pada pembanding, sehingga rentang menguji keanggotaan, kelas menguji jenis instans, dan Regexp menguji kecocokan string. - Beberapa pembanding dalam satu
whenditulis dipisahkan koma dan cocok apabila salah satunya cocok. caseadalah ekspresi yang menghasilkan nilai cabang yang dijalankan, dan menghasilkannilapabila tidak ada kecocokan tanpaelse.
Referensi#
- Control Expressions — Ruby — Dokumentasi resmi case/when beserta perilaku pencocokannya.
- Object#=== — Ruby — Dokumentasi operator === yang dipanggil oleh when beserta arti bawaannya.