Pattern adalah bentuk deklaratif untuk mencocokkan sebuah nilai terhadap pola tertentu sekaligus membongkarnya menjadi bagian-bagiannya. Topik ini membahas pattern pada deklarasi, pattern objek dengan pencocokan bidang, pattern list dengan elemen sisanya, serta pattern logika-or, dan diakhiri dengan program kecil yang menyatukannya. Setelah membacanya, pembongkaran nilai agregat dapat ditulis lebih ringkas daripada mengambil bidang satu per satu.
Pattern destrukturisasi deklarasi#
Destrukturisasi deklarasi menempatkan pattern di sisi kiri deklarasi var atau final, sehingga nilai di sisi kanan langsung terpecah menjadi variabel-variabel. Bentuk pattern selalu mengikuti bentuk nilainya, yaitu pattern kurung untuk record posisi dan pattern kurung siku untuk list. Contoh berikut membongkar record, list, dan titik koordinat dengan tiga pattern yang berbeda.
void main() {
var (nama, umur) = ('Ali', 19);
print('$nama berumur $umur tahun');
final [pertama, kedua, ketiga] = [10, 20, 30];
print('Nilai ujian: $pertama, $kedua, $ketiga');
final titik = (3, 4);
var (x, y) = titik;
print('Koordinat: x=$x, y=$y');
}Ali berumur 19 tahun
Nilai ujian: 10, 20, 30
Koordinat: x=3, y=4Keluaran menunjukkan bahwa setiap bidang langsung menjadi variabel dengan nama yang ditulis pada pattern. Cara ini menggantikan dua baris pengambilan bidang, misalnya titik.$1 dan titik.$2, dengan satu baris yang menyatakan maksudnya. Jumlah variabel pada pattern wajib cocok dengan jumlah bidang nilai yang dibongkar. Pada list, ketidakcocokan jumlah elemen menghentikan program saat berjalan dengan exception Pattern matching error. Pattern juga dapat disusun bertingkat, misalnya final (a, [b, c]) = (1, [2, 3]); yang membongkar record berisi list dalam satu deklarasi.
Selain pada deklarasi, pattern dapat digunakan pada beberapa tempat lain yang menerima bentuk pencocokan. Pernyataan if-case mencocokkan satu nilai terhadap satu pattern, klausa case pada switch menggunakan pattern per kasusnya, dan elemen for-in dapat membongkar setiap item secara langsung. Penugasan pattern, misalnya (a, b) = (b, a);, mengisi variabel yang sudah ada tanpa membuat deklarasi baru. Kumpulan tempat ini menjadikan pattern sebagai satu mekanisme tunggal untuk pembongkaran nilai, terlepas dari letak penggunaannya.
Pattern objek dan bidangnya#
Pattern objek mencocokkan tipe nilai dan bidangnya sekaligus, ditulis dengan nama kelas beserta bidang di dalam kurung. Subpattern konstan di dalamnya memeriksa nilai bidang, sedangkan subpattern variabel membongkar bidang menjadi variabel baru. Percabangan if-case menjadi tempat yang alami untuk menggunakan pattern objek.
class Titik {
final int x;
final int y;
Titik(this.x, this.y);
}
void main() {
for (final titik in [Titik(0, 0), Titik(3, 4)]) {
if (titik case Titik(x: 0, y: 0)) {
print('Pusat koordinat');
} else {
final Titik(x: x, y: y) = titik;
print('Titik di ($x, $y)');
}
}
}Pusat koordinat
Titik di (3, 4)Pada kasus pertama, pattern Titik(x: 0, y: 0) mencocokkan objek yang bertipe Titik dengan bidang x dan y bernilai 0, sehingga pembandingannya dilakukan dalam satu bentuk deklaratif. Kasus kedua memperlihatkan destrukturisasi objek, yaitu final Titik(x: x, y: y) = titik; yang membongkar kedua bidang menjadi variabel. Penulisannya dapat lebih pendek lagi dengan bentuk singkat bidang, misalnya final Titik(:x, :y) = titik; yang menghasilkan variabel dengan nama yang sama seperti bidangnya. Pattern objek tidak mengubah objeknya, karena yang berubah hanyalah tipe statis dan pengikatan variabelnya.
Bidang pada pattern objek dicocokkan melalui getter dengan nama yang sama, sehingga pencocokan tidak terbatas pada kelas yang dibuat sendiri. Subpattern variabel juga dapat diberi anotasi tipe, misalnya Titik(x: int px) yang menambah pemeriksaan tipe pada pengikatan. Apabila nilai bidang tidak cocok dengan anotasi tersebut, pencocokan gagal tanpa exception, dan kasus lain yang memeriksa nilai yang sama tetap dijalankan.
Pattern list dengan elemen sisanya#
Pattern list mencocokkan jumlah dan isi elemen list secara berurutan. Elemen sisanya (rest pattern) yang ditulis dengan ... menampung bagian tengah list yang jumlahnya tidak perlu dihitung secara manual, sehingga pattern tetap cocok untuk list yang panjangnya berubah-ubah.
void main() {
final nilaiUjian = [78, 85, 90, 88, 92];
final [pertama, kedua, ...tengah, terakhir] = nilaiUjian;
print('Pertama: $pertama');
print('Kedua: $kedua');
print('Tengah: $tengah');
print('Terakhir: $terakhir');
}Pertama: 78
Kedua: 85
Tengah: [90, 88]
Terakhir: 92Keluaran menunjukkan pembagian yang rapi, yaitu dua elemen pertama mengikat variabel pertama dan kedua, elemen terakhir mengikat variabel terakhir, sedangkan sisanya menjadi list baru bernama tengah. Variabel tengah bertipe List<int> karena elemen sisanya selalu menghasilkan list. Susunan seperti ini lazim untuk mengambil nilai di tepi sebuah daftar, misalnya nilai awal dan akhir ujian, tanpa perlu menghitung indeks tengahnya.
Elemen sisanya boleh ditulis tanpa nama, misalnya [pertama, ..., terakhir], apabila bagian tengahnya tidak diperlukan. Pengabaian satu elemen tunggal menggunakan pattern _, sehingga [_, kedua] mengambil elemen kedua saja. Bentuk-bentuk ini menjaga pattern tetap ringkas apabila hanya sebagian kecil posisi yang bermakna, dan pemeriksaan jumlah elemennya tetap ketat seperti pattern list biasa.
Pattern logika-or#
Pattern logika-or menggabungkan beberapa pola dengan tanda ||, dan pencocokan berhasil apabila salah satu pola cocok. Bentuk ini mengelompokkan nilai-nilai yang mendapat perlakuan sama tanpa mengulang cabangnya, sehingga daftar percabangan tetap pendek dan sejajar.
void main() {
for (final kode in ['A', 'C', 'E']) {
if (kode case 'A' || 'B') {
print('Kode $kode: hadir penuh');
} else if (kode case 'C' || 'D') {
print('Kode $kode: hadir sebagian');
} else {
print('Kode $kode: tidak dikenali');
}
}
}Kode A: hadir penuh
Kode C: hadir sebagian
Kode E: tidak dikenaliSetiap baris if (kode case ...) mencocokkan satu kelompok kode, dan kode yang tidak masuk kelompok mana pun jatuh ke cabang terakhir. Pencocokan logika-or berjalan dari kiri ke kanan dan berhenti pada pola pertama yang cocok, sehingga urutan penulisan menentukan pola mana yang diutamakan. Pola yang tidak cocok tidak mengikat variabel apa pun dari cabangnya, sehingga penggabungan pola yang mengikat variabel perlu dijaga agar maksudnya tetap jelas. Pattern logika-or juga dapat digabungkan dengan pattern lain, misalnya 'A' || 'B' || [_, _] yang mencocokkan dua teks tertentu atau list berisi dua elemen. Semakin sedikit pattern yang digabung dalam satu baris, semakin mudah cabangnya ditafsirkan, sehingga penggabungan sebaiknya dijaga tetap pendek. Untuk kelompok yang terus bertambah, switch dengan kasus terpisah biasanya lebih mudah dipelihara daripada satu baris gabungan yang panjang.
Menyusun pattern dalam satu program#
Ketiga kelompok pattern di atas bekerja dengan baik dalam satu program. Contoh berikut mengatur jadwal piket sederhana, yaitu membongkar tugas harian dari record, memotong daftar nomor urut dengan elemen sisanya, dan mengelompokkan hari dengan pattern logika-or.
// Program jadwal piket kecil yang memakai pattern.
// Menunjukkan destrukturisasi, pattern list, dan pattern logika-or.
void main() {
final tugas = ('Ali', 'membersihkan papan tulis');
var (nama, tugasHarian) = tugas;
print('$nama bertugas $tugasHarian');
final nomorUrutan = [2, 4, 6, 8];
final [pertama, ...tengah, terakhir] = nomorUrutan;
print('Urutan awal: $pertama');
print('Urutan tengah: $tengah');
print('Urutan akhir: $terakhir');
final hari = 6;
if (hari case 6 || 7) {
print('Hari ke-$hari akhir pekan, piket tidak dilaksanakan');
} else {
print('Hari ke-$hari hari kerja, piket berjalan seperti biasa');
}
}Ali bertugas membersihkan papan tulis
Urutan awal: 2
Urutan tengah: [4, 6]
Urutan akhir: 8
Hari ke-6 akhir pekan, piket tidak dilaksanakanSetiap blok kode di program tersebut menggantikan penulisan manual yang lebih panjang, yaitu pengambilan bidang berurutan, pemotongan list dengan sublist, dan deretan perbandingan ==. Pattern membuat maksud baris terbaca langsung dari bentuknya, dan analyzer tetap memeriksa tipe setiap pengikatan. Apabila struktur tugas bertambah satu bidang, analyzer menandai setiap destrukturisasi yang belum disesuaikan, sehingga perbaikannya dapat dikerjakan dari daftar error kompilasi.
Urutan blok pada program itu juga memperlihatkan pembagian tugas yang lazim, yaitu pattern destrukturisasi untuk data yang bentuknya tetap, elemen sisanya untuk daftar yang panjangnya berubah, dan pattern logika-or untuk pengelompokan nilai konstan. Ketiganya dapat dipadukan secara bertingkat, misalnya list berisi record yang setiap elemennya dibongkar langsung pada for-in. Dengan paduan tersebut, pembongkaran nilai tidak lagi memerlukan baris akses bidang yang terserak di banyak tempat.
Ringkasan#
- Pattern pada deklarasi
vardanfinalmembongkar record, list, atau objek menjadi variabel bernama dalam satu baris. - Pattern objek mencocokkan tipe dan bidang, dengan subpattern konstan untuk memeriksa nilai dan bentuk singkat
:bidanguntuk pengikatan. - Pattern list mencocokkan elemen berurutan, dan elemen sisanya
...menampung bagian tengah sebagai list baru. - Pattern logika-or menggabungkan beberapa pola dengan
||, sehingga nilai-nilai yang diperlakukan sama berada dalam satu cabang.
Referensi#
- Patterns — dart.dev — Dokumentasi resmi pattern Dart, termasuk pattern destrukturisasi, objek, list, dan logika-or.
- Effective Dart — dart.dev — Panduan gaya resmi Dart untuk penulisan kode yang konsisten.