Alur kendali

Pernyataan if, unless, while, case, dan ekspresi ternary dalam Crystal.

Daftar isi

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.

crystal kategori-suhu.cr
# 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 status

Jalankan berkasnya dengan perintah berikut.

bash
# jalankan program kategori-suhu.cr
crystal run kategori-suhu.cr
text Keluaran
"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.

crystal Contoh: percabangan 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
text Keluaran
"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.

crystal hitung-langkah.cr
# Perulangan while dengan kondisi di awal

langkah = 0

while langkah < 3
  langkah += 1
  p langkah
end

p "selesai"
text Keluaran
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.

crystal Contoh: break menghentikan dan next melompati putaran
angka = 0

while angka < 10
  angka += 1
  next if angka.odd?
  p angka
  break if angka == 6
end

p "berhenti"
text Keluaran
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.

crystal predikat-nilai.cr
# 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
text Keluaran
"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.

crystal Contoh: case dengan nilai tunggal sebagai pola
perintah = "mulai"

tindakan = case perintah
           when "mulai"
             "memulai"
           when "jeda"
             "menjeda"
           else
             "tidak dikenal"
           end

p tindakan
text Keluaran
"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.

crystal Contoh: case tanpa else tidak menemukan kecocokan
nilai = 50

hasil = case nilai
        when 90..100
          "A"
        end

p hasil
text Keluaran
nil

Tipe 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.

crystal Contoh: case dengan tipe sebagai pola
nilai = 3.14

jenis = case nilai
        when Int32
          "bilangan bulat"
        when Float64
          "bilangan desimal"
        else
          "tipe lain"
        end

p jenis
text Keluaran
"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.

crystal Contoh: case tanpa subjek
bilangan = 42

deskripsi = case
            when bilangan < 0
              "negatif"
            when bilangan == 0
              "nol"
            else
              "positif"
            end

p deskripsi
text Keluaran
"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.

crystal Contoh: ternary serta if dan unless postfix
stok = 0
label = stok == 0 ? "habis" : "tersedia"
p label

sisa = 3
p "stok tersisa #{sisa}" if sisa > 0
p "stok kosong" unless sisa > 0
text Keluaran
"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.

crystal Contoh: elsif pada unless
hujan = false

unless hujan
  p "langit cerah"
elsif langit == "berawan"
  p "berawan"
end
text Keluaran
In 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, dan elsif membentuk percabangan, sedangkan while mengulang tubuhnya selama kondisinya benar dan break serta next mengendalikan putarannya.
  • case mencocokkan subjek dengan pola when yang dapat berupa nilai, rentang, atau tipe, dan dapat ditulis tanpa subjek sebagai rangkaian kondisi.
  • Ternary serta if dan unless postfix memadatkan keputusan satu baris, sedangkan percabangan yang panjang lebih jelas dengan bentuk utuhnya.
  • if, unless, dan case adalah ekspresi, sehingga hasil cabang yang terpilih dapat ditampung ke dalam variabel.

Referensi#