Perulangan

Perulangan while, for gaya C, dan foreach untuk menelusuri list, termasuk peran variabel default $_.

Daftar isi

Percabangan memilih satu jalur di antara beberapa kemungkinan, sedangkan perulangan mengulang sekelompok pernyataan selama syaratnya masih terpenuhi. Topik ini membahas tiga bentuk perulangan pada Perl, yaitu while yang berulang berdasarkan kondisi, for gaya C yang didorong oleh penghitung, dan foreach yang menelusuri list. Variabel default $_ juga dibahas karena foreach tanpa variabel penerima menempatkan setiap elemen pada variabel tersebut. Setelah topik ini dipahami, bentuk perulangan dapat dipilih sesuai bentuk datanya dan ditulis tanpa jebakan yang lazim.

Perulangan while#

Pernyataan while menjalankan bloknya berulang kali selama kondisinya dinilai benar, dan kondisi dinilai kembali sebelum setiap putaran. Sama seperti pada percabangan, kondisi ditulis tanpa tanda kurung, sedangkan blok kurung kurawalnya wajib. Perulangan while tepat digunakan apabila jumlah putaran belum diketahui di awal dan berhentinya ditentukan oleh keadaan data.

Skrip berikut memproses antrean tiket loket sampai antreannya habis. Ekspresi @antrean pada posisi kondisi dinilai dalam konteks scalar sehingga menghasilkan jumlah elemen array tersebut. Selama array masih berisi elemen, nilainya benar, dan begitu elemen terakhir diambil dengan shift, kondisinya menjadi 0 yang dinilai salah.

perl antrean.pl
use strict;
use warnings;

my @antrean = ('Tiket A01', 'Tiket A02', 'Tiket A03');

while (@antrean) {
    my $tiket = shift @antrean;
    print "Memproses $tiket\n";
}

print "Antrean kosong, perulangan berhenti\n";
text Keluaran
Memproses Tiket A01
Memproses Tiket A02
Memproses Tiket A03
Antrean kosong, perulangan berhenti

Perulangan di atas berhenti karena setiap putaran mengurangi isi antrean satu elemen. Pernyataan terakhir berada di luar blok, sehingga pernyataan tersebut baru tereksekusi setelah kondisi berubah menjadi salah. Pola while semacam ini umum digunakan untuk memproses data baris demi baris, termasuk data yang dibaca dari berkas.

Perulangan for gaya C#

Bentuk for gaya C menata perulangan yang didorong oleh penghitung. Tiga bagian pada kepalanya ditulis di dalam tanda kurung dan dipisahkan titik koma, yaitu inisialisasi yang dijalankan sekali di awal, kondisi yang dinilai sebelum setiap putaran, dan langkah yang dijalankan setelah setiap putaran. Berbeda dengan kondisi if, tanda kurung pada for merupakan bagian wajib dari sintaksnya.

Skrip berikut mencetak tabel perkalian 7 untuk penghitung 1 sampai 5.

perl tabel-perkalian.pl
use strict;
use warnings;

for (my $i = 1; $i <= 5; $i++) {
    print "7 x $i = ", 7 * $i, "\n";
}
text Keluaran
7 x 1 = 7
7 x 2 = 14
7 x 3 = 21
7 x 4 = 28
7 x 5 = 35

Variabel $i dideklarasikan dengan my pada bagian inisialisasi, sehingga cakupannya terbatas pada perulangan itu saja. Kondisi $i <= 5 menentukan putaran terakhir, sedangkan $i++ menaikkan penghitung satu angka setelah setiap putaran. Tanda titik koma yang memisahkan tiga bagian tersebut merupakan bagian dari sintaks for dan bukan penanda akhir pernyataan. Ketiga bagian itu sendiri boleh dikosongkan, dan bentuk for (;;) yang mengosongkan semuanya merupakan idiom perulangan tanpa henti yang penghentinya dikelola di dalam blok.

Gaya C ini bersaing dengan foreach untuk kasus penghitungan sederhana. Apabila tujuan perulangan hanyalah menelusuri sekumpulan nilai, foreach dengan operator range lebih ringkas dan menghindari kesalahan off-by-one, yaitu putaran yang kurang atau lebih satu dari yang dimaksud.

Perulangan foreach dan operator range#

Pernyataan foreach menelusuri seluruh elemen sebuah list, satu elemen untuk setiap putaran, tanpa penghitung dan tanpa risiko salah batas. Kata kunci for dan foreach bersinonim pada Perl, tetapi nama foreach digunakan di bagian ini karena menyebutkan tujuannya dengan lebih jelas. List yang ditelusuri dapat berupa array maupun list yang dibangun langsung dengan operator range (range operator).

Operator range ditulis .. dan membangun list berurutan dari nilai awal sampai nilai akhir, sehingga 1 .. 3 menghasilkan list 1, 2, dan 3. Kedua ujung rentangnya ikut dimuat, sehingga 1 .. 5 memuat lima elemen. Sifat ini menjadikan operator range pilihan yang aman untuk menetapkan batas perulangan.

Skrip berikut menelusuri array daftar belanja, kemudian menelusuri list hasil operator range untuk menandai nomor urut.

perl rekap-belanja.pl
use strict;
use warnings;

my @belanjaan = ('beras', 'minyak goreng', 'telur');

foreach my $barang (@belanjaan) {
    print "- $barang\n";
}

print "Pemeriksaan nomor urut:\n";

foreach my $nomor (1 .. 3) {
    print "Baris $nomor selesai diperiksa\n";
}
text Keluaran
- beras
- minyak goreng
- telur
Pemeriksaan nomor urut:
Baris 1 selesai diperiksa
Baris 2 selesai diperiksa
Baris 3 selesai diperiksa

Variabel penerima dideklarasikan dengan my tepat setelah kata kunci foreach, dan variabel tersebut memegang satu elemen list untuk setiap putaran. Elemen yang diterima merupakan salinan nilai, sehingga mengubah $barang di dalam blok tidak mengubah isi @belanjaan. foreach juga menerima list hasil fungsi array seperti sort atau reverse, sehingga satu perulangan foreach dapat menggantikan for gaya C pada hampir semua kasus penelusuran data.

Variabel default $_#

Variabel $_ adalah variabel default Perl yang menjadi argumen tersirat banyak operasi apabila argumennya tidak diberikan. Pada foreach tanpa variabel penerima, $_ menjadi alias bagi elemen yang sedang ditelusuri, sehingga print; tanpa argumen mencetak elemen tersebut dan fungsi seperti sqrt yang dipanggil tanpa argumen bekerja pada elemen itu pula. Sifat alias ini berarti penugasan kepada $_ menulis ulang elemen aslinya, berbeda dengan variabel penerima my yang memegang salinan.

Skrip berikut memanggil sqrt tanpa argumen pada perulangan pertama, kemudian menugaskan hasil ucfirst kepada $_ pada perulangan kedua. Fungsi ucfirst menjadikan huruf pertama sebuah string kapital.

perl default-dollar.pl
use strict;
use warnings;

my @angka = (4, 9, 16);

foreach (@angka) {
    print sqrt, "\n";
}

my @kata = ('kuda', 'kucing');

foreach (@kata) {
    $_ = ucfirst;
    print;
    print "\n";
}
text Keluaran
2
3
4
Kuda
Kucing

Tiga baris pertama pada keluaran adalah akar kuadrat dari $_, yaitu elemen @angka yang sedang ditelusuri. Pada perulangan kedua, penugasan kepada $_ menulis ulang elemen @kata yang sedang diwakilinya, sehingga isi array aslinya ikut berubah menjadi berawalan huruf kapital. Fungsi bawaan lain yang mengikuti pola yang sama antara lain length, chomp, dan abs.

Gaya modern menyarankan variabel penerima dengan nama yang jelas apabila prosesnya panjang, karena kode yang bergantung penuh pada $_ sulit dibaca apabila perulangannya bersarang. Gunakan $_ pada perulangan pendek yang tindakannya sepele. Beri nama variabelnya apabila isi elemen dirujuk berulang kali atau apabila perubahan pada array aslinya tidak diinginkan.

Kesalahan umum#

Kesalahan pertama adalah perulangan while yang tidak pernah berhenti. Penyebabnya adalah badan perulangan yang tidak mengubah keadaan yang diperiksa, misalnya array yang tidak pernah dikurangi atau penghitung yang tidak dinaikkan, sehingga kondisinya tetap benar dan program tampak macet. Perbaikannya adalah memastikan setiap putaran menggerakkan keadaan menuju kondisi berhenti, misalnya mengurangi array atau menaikkan penghitung.

Kesalahan kedua adalah salah menghitung putaran pada for gaya C, yaitu kesalahan yang dikenal sebagai off-by-one. Kondisi $i < 5 dengan $i dimulai dari 1 menghasilkan empat putaran, sedangkan $i <= 5 menghasilkan lima putaran. Operator range tidak mengalami kerancuan ini karena 1 .. 5 secara eksplisit memuat kedua ujungnya. Perbaikannya adalah memutuskan lebih dahulu apakah batas akhir ikut diproses, kemudian memilih < atau <= sesuai keputusan itu.

Kesalahan ketiga adalah memperlakukan $_ sebagai salinan. Variabel tersebut adalah alias bagi elemen yang sedang ditelusuri, sehingga penugasan kepada $_ mengubah array aslinya, dan perubahan itu sering tak terduga apabila array yang sama digunakan kembali di bagian lain skrip. Perbaikannya adalah menggunakan variabel penerima bernama, seperti foreach my $item, apabila elemen tidak boleh diubah.

Ringkasan#

  • while mengulang bloknya selama kondisi benar dan tepat untuk jumlah putaran yang belum diketahui di awal.
  • for gaya C menata penghitung dalam tiga bagian yang dipisahkan titik koma, yaitu inisialisasi, kondisi, dan langkah.
  • foreach menelusuri list satu elemen per putaran, termasuk list hasil operator range ...
  • Pada foreach tanpa variabel penerima, $_ menjadi alias elemen aktif, sehingga print; mencetaknya dan penugasan kepada $_ mengubah elemen aslinya.

Referensi#