Program jarang berjalan sebagai urutan pernyataan yang lurus, karena keputusan dan pengulangan menentukan langkah berikutnya. Topik ini membahas pernyataan alur kendali di Crystal, yaitu if dan unless untuk percabangan, while untuk perulangan, serta case dan when untuk pemilihan pola, termasuk bentuk ternary dan postfix yang memadatkannya. Konstruksi percabangan dan pemilihannya adalah ekspresi, sehingga nilainya dapat ditampung ke dalam variabel.
Percabangan dengan if, unless, dan elsif#
Pernyataan if menjalankan cabang pertama apabila kondisinya benar dan cabang else apabila salah. Kebalikannya disediakan oleh unless, yaitu tubuhnya berjalan apabila kondisinya salah, dan unless juga dapat membawa cabang else. Program berikut menggunakan keduanya sebagai ekspresi, sehingga hasilnya ditampung ke dalam variabel.
# if dan unless sebagai ekspresi
suhu = 31
kategori = if suhu > 30
"panas"
else
"sedang"
end
hujan = false
status = unless hujan
"langit cerah"
else
"bawa payung"
end
p kategori
p statusJalankan berkasnya dengan perintah berikut.
# jalankan program kategori-suhu.cr
crystal run kategori-suhu.cr"panas"
"langit cerah"Blok if memilih "panas" karena suhu bernilai 31, sedangkan blok unless memilih "langit cerah" karena hujan bernilai false. Kedua blok ditutup dengan end, dan nilai cabang yang terpilih menjadi nilai seluruh ekspresinya. Apabila keputusannya lebih dari dua, cabang tambahan ditulis dengan elsif.
jam = 21
salam = if jam < 11
"Selamat pagi"
elsif jam < 15
"Selamat siang"
elsif jam < 19
"Selamat sore"
else
"Selamat malam"
end
p salam"Selamat malam"Compiler menilai kondisi dari atas ke bawah, dan cabang pertama yang kondisinya benar menjadi hasilnya. Pada contoh tersebut, dua kondisi pertama bernilai false sehingga cabang else yang dipilih.
Perulangan while#
Pernyataan while mengevaluasi kondisinya sebelum setiap putaran, dan tubuhnya berjalan selama kondisi bernilai true. Jumlah putaran tidak dituliskan di mana pun, sehingga ada pernyataan di dalam tubuh yang mengubah kondisi agar perulangan berakhir.
# Perulangan while dengan kondisi di awal
langkah = 0
while langkah < 3
langkah += 1
p langkah
end
p "selesai"1
2
3
"selesai"Pernyataan langkah += 1 menaikkan nilai variabel pada setiap putaran, sehingga kondisi langkah < 3 pada akhirnya bernilai false dan eksekusi berlanjut ke pernyataan di bawah end. Dua pernyataan tambahan mengendalikan putaran, yaitu break yang menghentikan seluruh perulangan dan next yang melompat ke putaran berikutnya.
angka = 0
while angka < 10
angka += 1
next if angka.odd?
p angka
break if angka == 6
end
p "berhenti"2
4
6
"berhenti"Pernyataan next melewatkan bilangan ganjil, sehingga hanya bilangan genap yang dicetak, dan break mengakhiri perulangan saat angka mencapai 6 meskipun kondisi angka < 10 masih benar.
Case dengan rentang dan nilai#
Konstruksi case membandingkan subjeknya dengan setiap pola when dari atas ke bawah, dan pencocokan dilakukan dengan metode === milik polanya. Karena rentang mengimplementasikan ===, rentang dapat digunakan sebagai pola tanpa penulisan kondisi per nilai.
# case dengan rentang nilai
nilai = 85
predikat = case nilai
when 90..100
"A"
when 80..89
"B"
when 70..79
"C"
else
"D"
end
p predikat"B"Nilai 85 tidak termuat pada rentang pertama, tetapi termuat pada 80..89, sehingga cabang kedua yang dipilih. Pola when juga dapat berupa nilai tunggal, baik bilangan maupun string, dan beberapa nilai dapat dijadikan satu pola dengan pemisah koma.
perintah = "mulai"
tindakan = case perintah
when "mulai"
"memulai"
when "jeda"
"menjeda"
else
"tidak dikenal"
end
p tindakan"memulai"Penulisan cabang else pada case bersifat opsional, tetapi ketiadaannya menimbulkan konsekuensi tipe. Apabila tidak ada pola yang cocok dan else tidak dituliskan, nilai seluruh ekspresinya adalah nil.
nilai = 50
hasil = case nilai
when 90..100
"A"
end
p hasilnilTipe yang disimpulkan untuk hasil pada contoh ini adalah String | Nil, yaitu gabungan String dan Nil, sebab kemungkinan tidak ada pola yang cocok tetap dihitung oleh compiler.
Case terhadap tipe dan tanpa subjek#
Pola when juga dapat berupa tipe, sehingga percabangan berdasarkan jenis nilai ditulis dengan bentuk case yang sama. Pencocokan tetap menggunakan ===, yang pada tipe berarti pemeriksaan keanggotaan tipe terhadap subjeknya.
nilai = 3.14
jenis = case nilai
when Int32
"bilangan bulat"
when Float64
"bilangan desimal"
else
"tipe lain"
end
p jenis"bilangan desimal"Bentuk lain yang tersedia adalah case tanpa subjek, yaitu setiap when langsung berisi ekspresi bersyarat yang dinilai kebenarannya. Bentuk ini menggantikan rangkaian if dan elsif yang panjang agar setiap kondisi berdiri pada barisnya sendiri.
bilangan = 42
deskripsi = case
when bilangan < 0
"negatif"
when bilangan == 0
"nol"
else
"positif"
end
p deskripsi"positif"Ternary dan bentuk postfix#
Pilihan antara dua nilai dapat ditulis satu baris dengan operator ternary, yaitu kondisi ? nilai_benar : nilai_salah. if dan unless juga dapat ditulis dalam bentuk postfix, yaitu kondisinya diletakkan setelah pernyataan yang akan dijalankan.
stok = 0
label = stok == 0 ? "habis" : "tersedia"
p label
sisa = 3
p "stok tersisa #{sisa}" if sisa > 0
p "stok kosong" unless sisa > 0"habis"
"stok tersisa 3"Ternary memilih "habis" karena stok bernilai 0, sedangkan if postfix menjalankan pencetakannya karena kondisinya benar. Baris terakhir tidak mencetak apa pun karena kondisi sisa > 0 bernilai true, sedangkan tubuh unless hanya berjalan apabila kondisinya salah.
Bentuk padat ini tepat untuk satu pernyataan pendek. Apabila tubuhnya bertambah, bentuk if dan unless utuh yang diakhiri end lebih mudah dibaca.
Kesalahan umum#
Menulis elsif pada unless. Konstruksi unless tidak memiliki cabang elsif, sehingga program ditolak compiler. Program dengan isi berikut disimpan sebagai salah-unless.cr, lalu dijalankan.
hujan = false
unless hujan
p "langit cerah"
elsif langit == "berawan"
p "berawan"
endIn salah-unless.cr:5:1
5 | elsif langit == "berawan"
^
Error: expecting identifier 'end', not 'elsif'Perbaikannya, gunakan if utuh apabila percabangannya lebih dari dua cabang, atau pisahkan ke blok unless dan if tersendiri.
Lupa menutup blok dengan end. Setiap if, unless, while, dan case membuka blok yang wajib ditutup end. Pesan error yang dilaporkan compiler menunjuk tempat pembacaan berhenti, yang tidak selalu sama dengan baris yang kekurangan end, sehingga periksa susunan blok dari yang terdalam ketika error semacam itu muncul.
Ringkasan#
if,unless, danelsifmembentuk percabangan, sedangkanwhilemengulang tubuhnya selama kondisinya benar danbreaksertanextmengendalikan putarannya.casemencocokkan subjek dengan polawhenyang dapat berupa nilai, rentang, atau tipe, dan dapat ditulis tanpa subjek sebagai rangkaian kondisi.- Ternary serta
ifdanunlesspostfix memadatkan keputusan satu baris, sedangkan percabangan yang panjang lebih jelas dengan bentuk utuhnya. if,unless, dancaseadalah ekspresi, sehingga hasil cabang yang terpilih dapat ditampung ke dalam variabel.
Referensi#
- Referensi bahasa Crystal — Crystal Language Reference — Dokumentasi sintaks percabangan, perulangan, case, dan operator ternary.
- Dokumentasi API Crystal 1.22.1 — Dokumentasi API Crystal
— Rincian metode
===pada rentang dan tipe yang digunakan pencocokan case.