Referensi (reference) adalah nilai scalar yang menyimpan alamat dari data lain, sehingga data asli dapat dicapai tanpa perlu disalin. Topik ini membahas pembuatan referensi dengan operator backslash, pengaksesan data melalui sigil ganda dan sintaks panah, pengenalan jenis referensi dengan ref(), serta pembuatan referensi anonim yang menjadi fondasi struktur data bersarang.
Referensi sebagai alamat menuju data#
Array dan hash hanya dapat menampung nilai scalar, sedangkan satu informasi sering terdiri atas banyak nilai, misalnya satu siswa memiliki nama dan beberapa nilai ujian. Referensi menjembatani keterbatasan itu karena referensi sendiri berupa scalar biasa, sehingga dapat disimpan sebagai elemen array atau nilai hash. Dengan menyimpan alamat, satu slot penampung mampu menunjuk struktur data berukuran berapa pun. Perl menghitung banyaknya referensi menuju setiap data, sehingga data yang ditunjuk tetap hidup selama minimal satu referensinya masih ada dan dibersihkan setelah referensi terakhirnya hilang.
Apabila variabel referensi dicetak langsung, Perl menampilkan alamatnya dalam bentuk seperti SCALAR(0x558f1a2b3c40). Bagian setelah 0x adalah alamat memori yang berbeda pada setiap eksekusi, sehingga nilai itu tidak layak dijadikan keluaran program. Yang berguna adalah data yang dicapai melalui alamat tersebut, dan cara mengaksesnya dibahas pada bagian berikutnya. Skema berikut memperlihatkan hubungan variabel referensi dengan array yang ditunjuknya. Ukuran referensi juga tetap kecil berapa pun besar data yang ditunjuknya, sehingga meneruskan referensi ke subrutin jauh lebih murah daripada menyalin seluruh isinya.
Membuat referensi dengan operator backslash#
Operator backslash ditempatkan di depan variabel untuk menghasilkan referensi menuju variabel itu. Bentuknya \$x untuk variabel scalar, \@warna untuk array, dan \%stok untuk hash. Referensi yang dihasilkan disimpan pada variabel scalar biasa, sehingga penamaannya bebas, meskipun awalan ref_ pada contoh membantu keterbacaan. Operator yang sama juga diterapkan pada subrutin berupa \&nama, dan hasilnya berupa referensi kode yang dapat dipanggil melalui sintaks panah.
Skrip berikut membuat tiga referensi dari tiga jenis variabel, lalu mengenali jenisnya dengan ref(). Hasilnya menegaskan bahwa referensi menuju array tetap berupa nilai scalar yang menunjuk array.
use strict;
use warnings;
my $angka = 42;
my @warna = ("merah", "hijau", "biru");
my %stok = (pensil => 12, buku => 5);
my $ref_angka = \$angka;
my $ref_warna = \@warna;
my $ref_stok = \%stok;
print ref($ref_angka), " menuju nilai tunggal\n";
print ref($ref_warna), " menuju array\n";
print ref($ref_stok), " menuju hash\n";SCALAR menuju nilai tunggal
ARRAY menuju array
HASH menuju hashReferensi juga dapat dibuat terhadap satu elemen array atau hash, misalnya \$daftar[0] dan \$stok{buku}. Membuat referensi tidak menyalin data yang ditunjuk, sehingga perubahan pada data asli langsung terlihat melalui referensinya, dan sebaliknya perubahan melalui referensi langsung terlihat pada data aslinya. Sifat dua arah inilah yang dimanfaatkan subrutin untuk mengubah array atau hash milik pemanggilnya. Referensi menuju nilai literal juga sah, misalnya \42, tetapi nilai yang ditunjuknya bersifat hanya baca sehingga penulisan kepadanya memicu error.
Mengakses data melalui referensi#
Perl menyediakan dua bentuk sintaks untuk mencapai data yang ditunjuk referensi, dan keduanya disebut dereferensi (dereference). Bentuk pertama menempelkan sigil data di depan referensi, yaitu $$ref_angka untuk nilai scalar, @$ref_warna untuk array, dan %$ref_stok untuk hash. Bentuk kedua menggunakan panah -> untuk mencapai satu elemen, yaitu $ref_warna->[1] untuk elemen array dan $ref_stok->{buku} untuk nilai hash. Bentuk sigil ganda juga dapat ditulis dengan kurung kurawal, misalnya @{ $ref_warna }, dan bentuk berkurung ini wajib apabila isi di dalamnya lebih panjang daripada satu nama variabel.
Skrip berikut menggunakan kedua bentuk tersebut, termasuk mengubah data asli melalui referensinya.
use strict;
use warnings;
my $angka = 42;
my @warna = ("merah", "hijau", "biru");
my %stok = (pensil => 12, buku => 5);
my $ref_angka = \$angka;
my $ref_warna = \@warna;
my $ref_stok = \%stok;
# dereferensi penuh dengan sigil ganda
print "Nilai angka: $$ref_angka\n";
print "Jumlah warna: ", scalar(@$ref_warna), "\n";
# akses satu elemen dengan panah
print "Warna kedua: $ref_warna->[1]\n";
print "Stok buku: $ref_stok->{buku}\n";
# mengubah data asli lewat referensinya
push @$ref_warna, "kuning";
print "Warna terakhir kini: $warna[-1]\n";Nilai angka: 42
Jumlah warna: 3
Warna kedua: hijau
Stok buku: 5
Warna terakhir kini: kuningBaris terakhir keluaran menunjukkan bahwa push yang ditujukan ke @$ref_warna menambah elemen pada @warna, yaitu array aslinya. Dereferensi penuh seperti @$ref_warna mengekspos seluruh array sehingga dapat langsung diperlakukan sebagai array oleh fungsi apa pun, sedangkan panah menyelesaikan akses satu elemen dengan lebih ringkas. Keduanya saling melengkapi, dan panah menjadi tulang punggung akses pada struktur bersarang yang lebih dalam. Panah juga dapat dirangkai melewati beberapa tingkat, misalnya $struktur->[0]{nama}[1], dan setiap panah mengikuti satu alamat pada tingkatnya. Rangkaian seperti itu menjadi pola utama pada topik Data kompleks.
Mengenali jenis referensi dengan ref()#
Fungsi ref() menerima satu nilai dan mengembalikan jenis referensinya berupa string, yaitu SCALAR untuk nilai tunggal, ARRAY untuk array, dan HASH untuk hash. Apabila argumennya bukan referensi, ref() mengembalikan string kosong. Pemeriksaan ini berguna sebelum melakukan dereferensi, karena sigil yang tidak sesuai dengan jenis referensinya memicu error ketika program berjalan. Jenis lainnya juga dikenali, yaitu CODE untuk referensi subrutin dan nama paket untuk referensi yang telah dijadikan objek.
Skrip berikut memeriksa referensi yang baru dibuat sekaligus satu nilai biasa sebagai pembandingnya.
use strict;
use warnings;
my $angka = 42;
my @daftar = (10, 20, 30);
my %stok = (pensil => 12);
print "ref(\$angka): ", ref(\$angka), "\n";
print "ref(\@daftar): ", ref(\@daftar), "\n";
print "ref(\%stok): ", ref(\%stok), "\n";
print "ref(42): ", ref(42), "\n";ref($angka): SCALAR
ref(@daftar): ARRAY
ref(%stok): HASH
ref(42): Baris terakhir keluaran tampak kosong karena ref(42) menghasilkan string kosong. Pada program yang menerima struktur data dari subrutin lain, hasil ref() dapat dijadikan syarat percabangan sebelum data diolah, sehingga kesalahan jenis tertangkap lebih dahulu sebelum sempat menjadi error dereferensi. Pemeriksaan ini murah karena ref() hanya membaca label jenis yang sudah tersimpan pada data tersebut. Subrutin yang menuntut jenis tertentu juga dapat menolak argumennya lebih awal dengan pesan yang jelas, alih-alih menunggu error dereferensi yang kurang menjelaskan konteksnya.
Referensi anonim#
Referensi sejauh ini dibuat dari variabel yang sudah ada. Perl juga menyediakan referensi anonim (anonymous), yaitu referensi menuju struktur yang langsung ditulis tanpa variabel perantara. Kurung siku [ ... ] membuat array anonim, sedangkan kurung kurawal { ... } membuat hash anonim, dan keduanya menghasilkan referensi yang siap disimpan dalam satu ekspresi. Struktur yang dibuatnya tidak memiliki nama, sehingga satu-satunya cara mencapainya adalah melalui referensi yang menyimpan alamatnya.
Skrip berikut menyimpan array anonim dan hash anonim pada dua variabel scalar, lalu membaca isinya melalui panah.
use strict;
use warnings;
# array anonim dengan kurung siku dan hash anonim dengan kurung kurawal
my $titik = [3, 8];
my $belanja = { pensil => 2000, buku => 8500 };
print "Koordinat: $titik->[0], $titik->[1]\n";
print "Harga buku: $belanja->{buku}\n";Koordinat: 3, 8
Harga buku: 8500Kelebihan referensi anonim adalah struktur yang dihasilkan langsung lahir di tempat yang membutuhkannya, misalnya sebagai elemen array atau sebagai nilai hash, sehingga penulisan struktur bersarang menjadi ringkas. Kurung siku dan kurung kurawal ini berbeda makna dengan tanda kurung pembuat daftar biasa, dan pembedaan itu menjadi kunci pada topik Data kompleks. Setiap evaluasi kurung siku atau kurung kurawal juga menghasilkan struktur baru yang berdiri sendiri, sehingga ekspresi yang sama di dalam perulangan menghasilkan banyak rekaman yang terpisah. Sifat inilah yang digunakan untuk membangun struktur data secara bertahap saat program berjalan.
Kesalahan umum#
Kesalahan yang mudah terjadi adalah menuliskan backslash di depan nama array yang berada di dalam tanda kurung, yaitu \(@angka), dengan harapan memperoleh satu referensi menuju array. Bentuk itu justru menghasilkan daftar referensi, satu untuk setiap elemennya, sehingga hasilnya bukan satu referensi ARRAY melainkan beberapa referensi SCALAR.
use strict;
use warnings;
my @angka = (10, 20, 30);
my $ke_array = \@angka; # satu referensi menuju seluruh array
my @ke_elemen = \(@angka); # daftar referensi, satu untuk setiap elemen
print "ref(\$ke_array): ", ref($ke_array), "\n";
print "ref(\$ke_elemen[0]): ", ref($ke_elemen[0]), "\n";
print "Nilai elemen pertama lewat referensi elemen: ${$ke_elemen[0]}\n";ref($ke_array): ARRAY
ref($ke_elemen[0]): SCALAR
Nilai elemen pertama lewat referensi elemen: 10Perbandingan pada skrip memperlihatkan bedanya secara langsung, yaitu \@angka menghasilkan satu referensi ARRAY, sedangkan \(@angka) menghasilkan referensi SCALAR per elemen. Apabila yang dibutuhkan adalah satu pintu menuju seluruh array, cukup tulis \@angka, dan bentuk \(@angka) hanya relevan ketika referensi per elemen memang diinginkan.
Ringkasan#
- Referensi adalah scalar yang menyimpan alamat data lain, dibuat dengan backslash berupa
\$x,\@arr, dan\%hash. - Data yang ditunjuk dicapai dengan sigil ganda seperti
$$refdan@$ref, atau dengan panah berupa$ref->[0]dan$ref->{kunci}. ref()mengembalikan jenis referensi berupaSCALAR,ARRAY, atauHASH, dan string kosong untuk nilai biasa.- Kurung siku
[ ... ]dan kurung kurawal{ ... }membuat referensi anonim tanpa variabel perantara.
Referensi#
- perlreftut — Perl documentation — Tutorial singkat penggunaan referensi untuk menyusun dan mengakses data.
- perlref — Perl documentation — Aturan lengkap pembuatan referensi, dereferensi, dan referensi anonim.
- perldata — Perl documentation — Sifat nilai scalar sebagai satu-satunya penampung yang dimiliki array dan hash.