Perulangan menjalankan sekumpulan pernyataan berulang kali, baik selama sebuah syarat terpenuhi maupun untuk setiap elemen dalam sebuah koleksi. Topik ini membahas while, until, dan loop untuk perulangan berbasis kondisi, kemudian iterator times, upto, downto, step, dan each yang menjadi gaya khas Ruby. Setelah membacanya, pemilihan bentuk perulangan untuk kasus berbasis hitungan maupun berbasis koleksi dapat dilakukan dengan pertimbangan yang tepat, lengkap dengan cara menghentikannya.
while dan until#
Pernyataan while mengulang badannya selama kondisi bernilai benar, dan kondisi dinilai sebelum setiap iterasi dimulai. Karena penilaian terjadi sebelum badan, badan tidak pernah dijalankan apabila kondisi langsung palsu sejak awal. Variabel yang terlibat dalam kondisi harus berubah di dalam badan, karena perubahan itulah yang membuat perulangan berakhir.
sisa = 3
while sisa > 0
puts "Menunggu #{sisa} menit"
sisa -= 1
end
puts "Selesai menunggu"Menunggu 3 menit
Menunggu 2 menit
Menunggu 1 menit
Selesai menungguAlur pemeriksaan kondisi dan pengulangannya digambarkan pada diagram berikut.
Kata kunci until adalah kebalikan dari while, yaitu mengulang badan sampai kondisinya bernilai benar. Bentuk ini nyaman untuk kondisi yang dinyatakan sebagai tujuan, misalnya menunggu sensor mencapai suhu tertentu. Contoh berikut menaikkan suhu satu derajat setiap iterasi hingga target tercapai.
suhu = 24
until suhu >= 26
puts "Suhu #{suhu} derajat, menunggu pemanasan"
suhu += 1
end
puts "Suhu target tercapai: #{suhu}"Suhu 24 derajat, menunggu pemanasan
Suhu 25 derajat, menunggu pemanasan
Suhu target tercapai: 26loop, break, dan next#
Metode loop mengulang blok (block) tanpa syarat apa pun. Blok adalah potongan kode di antara do dan end yang diserahkan ke metode untuk dijalankan. Perulangannya hanya berakhir melalui break. Kata kunci break menghentikan perulangan sepenuhnya, sedangkan next melompati sisa badan dan berlanjut ke iterasi berikutnya. Kombinasi keduanya memungkinkan perulangan berhenti menurut keadaan di tengah badan, bukan hanya menurut kondisi awal.
nomor_antrian = 0
loop do
nomor_antrian += 1
break if nomor_antrian > 4
next if nomor_antrian == 2
puts "Melayani nomor #{nomor_antrian}"
endMelayani nomor 1
Melayani nomor 3
Melayani nomor 4Nomor 2 dilewati oleh next tanpa mencetak apa pun, sedangkan nomor 5 tidak pernah tercetak karena break berjalan lebih dulu. Posisi break sebelum next menjamin perulangan berhenti walaupun syarat next juga terpenuhi. Urutan kedua kata kunci ini perlu diperiksa setiap kali keduanya digunakan bersama.
Iterator times, upto, dan kerabatnya#
Bilangan di Ruby menyediakan iterator, yaitu metode yang menjalankan blok secara berulang dengan jumlah langkah yang pasti. Metode times mengulang blok sebanyak nilai bilangannya dan menyampaikan indeks berjalan ke variabel blok. Metode upto, downto, dan step mengulang dari nilai awal menuju nilai akhir menurut arah dan panjang langkahnya.
3.times do |nomor|
puts "Piket hari ke-#{nomor + 1}"
endPiket hari ke-1
Piket hari ke-2
Piket hari ke-3Indeks yang disampaikan times dimulai dari nol, sehingga penomoran yang lazim dibaca manusia, seperti hari ke-1, memerlukan penjumlahan nomor + 1 di dalam interpolasi. Kebiasaan ini mengikuti konvensi pengindeksan Ruby secara umum. Contoh berikut memadukan tiga iterator bilangan dalam satu program.
1.upto(3) { |n| puts "Hari #{n}" }
5.downto(3) { |n| puts "Hitung mundur #{n}" }
0.step(12, 4) { |n| puts "Pemeriksaan menit #{n}" }Hari 1
Hari 2
Hari 3
Hitung mundur 5
Hitung mundur 4
Hitung mundur 3
Pemeriksaan menit 0
Pemeriksaan menit 4
Pemeriksaan menit 8
Pemeriksaan menit 12Bentuk 1.upto(3) menaikkan nilai satu per satu, 5.downto(3) menurunkannya, sedangkan 0.step(12, 4) melompat dengan jarak empat hingga batas 12. Ketiganya menghasilkan Enumerator apabila blok tidak diberikan, tetapi bentuk dengan blok seperti di atas adalah penggunaan sehari-harinya. Kurung kurawal pada contoh adalah bentuk blok lain selain do ... end, yang lazim digunakan untuk badan satu baris.
each dan gaya iterasi Ruby#
Untuk koleksi seperti array, Ruby lebih sering menggunakan metode each daripada while dengan variabel indeks. Metode each menjalankan blok untuk setiap elemen dan menyampaikan elemen itu ke variabel blok, sehingga penulisan indeks dan batas perulangan tidak diperlukan. Contoh berikut membagi jadwal piket dengan mengambil anggota dari urutan terdepan satu per satu.
# Penugasan piket dengan each sebagai gaya iterasi Ruby.
anggota = ["Ali", "Budi", "Citra", "Dewi", "Eka", "Farhan"]
hari = ["Senin", "Selasa", "Rabu", "Kamis"]
hari.each do |nama_hari|
petugas = anggota.shift
puts "#{nama_hari}: #{petugas}"
end
puts "Sisa anggota tanpa jadwal: #{anggota.join(", ")}"Senin: Ali
Selasa: Budi
Rabu: Citra
Kamis: Dewi
Sisa anggota tanpa jadwal: Eka, FarhanMetode shift mengambil elemen terdepan array sekaligus mengeluarkannya, sehingga baris keluaran terakhir menyisakan dua nama yang belum kebagian jadwal. Pola ini meniru perilaku antrean, yaitu yang datang lebih dulu dilayani lebih dulu. Variabel yang diterima blok hanya berlaku di dalam blok, sehingga tidak meninggalkan variabel sisa setelah perulangan berakhir.
Ruby juga menyediakan perulangan for ... in yang setara dengan each. Bentuk ini jarang digunakan dalam kode Ruby sehari-hari karena variabel iterasinya tetap tersedia setelah perulangan berakhir, berbeda dari variabel blok yang ikut hilang. Berikut bentuknya untuk perbandingan.
for n in 1..3
puts "Baris #{n}"
endBaris 1
Baris 2
Baris 3Kesalahan umum#
Kesalahan pertama adalah perulangan while yang kondisinya tidak pernah berubah. Menghapus baris sisa -= 1 pada contoh di atas membuat sisa > 0 selalu benar, sehingga program mencetak baris yang sama tanpa akhir dan hanya berhenti ketika dihentikan paksa dari terminal. Perulangan berbasis kondisi selalu memerlukan satu pernyataan yang menggerakkan keadaan menuju kondisi berakhir, dan baris itu paling aman ditulis lebih dulu, sebelum isi badan.
Kesalahan kedua adalah salah hitung batas, yang paling sering muncul pada times. Menulis puts "Piket hari ke-#{nomor}" tanpa penjumlahan menghasilkan urutan yang dimulai dari nol, sedangkan menggunakan <= pada while dengan batas yang sama menambah satu iterasi ekstra. Kebiasaan yang berguna adalah memutuskan lebih dulu apakah kasusnya berbasis indeks dari nol atau berbasis hitungan manusia, lalu tetap konsisten pada satu konvensi hingga badan perulangan selesai ditulis.
Ringkasan#
whilemengulang selama kondisi benar danuntilmengulang sampai kondisi benar, keduanya menilai kondisi sebelum setiap iterasi.loopmengulang blok tanpa syarat dan berakhir hanya melaluibreak, sedangkannextmelompat ke iterasi berikutnya.- Iterator
times,upto,downto, danstepmengulang dengan jumlah langkah pasti, dan indekstimesdimulai dari nol. eachmengiterasi setiap elemen koleksi dan menjadi gaya perulangan yang paling khas Ruby, sedangkanfor intersedia tetapi jarang digunakan.
Referensi#
- Control Expressions — Ruby — Dokumentasi resmi while, until, dan for beserta perilakunya.
- Kernel#loop — Ruby — Dokumentasi loop yang mengulang blok tanpa batas hingga break dijalankan.
- Integer#times — Ruby — Dokumentasi iterator times beserta kerabatnya upto, downto, dan step.