Ini ialah perintah perlref yang boleh dijalankan dalam penyedia pengehosan percuma OnWorks menggunakan salah satu daripada berbilang stesen kerja dalam talian percuma kami seperti Ubuntu Online, Fedora Online, emulator dalam talian Windows atau emulator dalam talian MAC OS.
JADUAL:
NAMA
perlref - Rujukan Perl dan struktur data bersarang
NOTA
Ini adalah dokumentasi lengkap tentang semua aspek rujukan. Untuk tutorial yang lebih pendek
pengenalan kepada ciri penting sahaja, lihat perlreftut.
DESCRIPTION
Sebelum mengeluarkan 5 Perl adalah sukar untuk mewakili struktur data yang kompleks, kerana
semua rujukan mestilah simbolik--dan walaupun begitu sukar untuk merujuk kepada pembolehubah
bukannya entri jadual simbol. Perl kini bukan sahaja memudahkan penggunaan simbolik
rujukan kepada pembolehubah, tetapi juga membolehkan anda mempunyai rujukan "keras" kepada mana-mana bahagian data atau
kod. Mana-mana skalar mungkin mempunyai rujukan keras. Kerana tatasusunan dan cincang mengandungi skalar,
anda kini boleh membina tatasusunan tatasusunan dengan mudah, tatasusunan cincangan, cincang tatasusunan, tatasusunan cincangan
cincang fungsi, dan sebagainya.
Rujukan keras adalah pintar--ia menjejaki kiraan rujukan untuk anda, secara automatik
membebaskan perkara yang dirujuk apabila kiraan rujukannya menjadi sifar. (Bilangan rujukan
untuk nilai dalam struktur data rujukan sendiri atau kitaran mungkin tidak mencapai sifar tanpa a
sedikit bantuan; lihat "Rujukan Pekeliling" untuk penjelasan terperinci.) Jika perkara itu berlaku
untuk menjadi objek, objek itu dimusnahkan. Lihat perlobj untuk maklumat lanjut tentang objek. (Didalam
rasa, segala-galanya dalam Perl ialah objek, tetapi kami biasanya menyimpan perkataan itu untuk rujukan
objek yang telah "diberkati" secara rasmi ke dalam pakej kelas.)
Rujukan simbolik ialah nama pembolehubah atau objek lain, sama seperti pautan simbolik dalam a
Sistem fail Unix mengandungi hanya nama fail. Notasi *glob ialah sesuatu a
rujukan simbolik. (Rujukan simbolik kadangkala dipanggil "rujukan lembut", tetapi
tolong jangan panggil mereka begitu; rujukan cukup mengelirukan tanpa sinonim yang tidak berguna.)
Sebaliknya, rujukan keras lebih seperti pautan keras dalam sistem fail Unix: Ia digunakan
untuk mengakses objek asas tanpa mengambil berat tentang nama (yang lain). Apabila
perkataan "rujukan" digunakan tanpa kata sifat, seperti dalam perenggan berikut, ia adalah
biasanya bercakap tentang rujukan yang sukar.
Rujukan mudah digunakan dalam Perl. Terdapat hanya satu prinsip utama: secara umum,
Perl tidak melakukan rujukan tersirat atau penyahrujukan. Apabila skalar memegang rujukan,
ia sentiasa berkelakuan sebagai skalar mudah. Ia tidak secara ajaib mula menjadi tatasusunan atau cincang
atau subrutin; anda perlu memberitahunya secara eksplisit untuk berbuat demikian, dengan membatalkan rujukannya.
Yang berkata, sedar bahawa Perl versi 5.14 memperkenalkan pengecualian kepada peraturan, untuk
kemudahan sintaksis. Tatasusunan eksperimen dan tingkah laku fungsi bekas cincang membenarkan
rujukan tatasusunan dan cincang untuk dikendalikan oleh Perl seolah-olah mereka telah secara eksplisit
dinyahrujuk secara sintaksis. Lihat "Peningkatan Sintaksis" dalam perl5140delta dan perlfunc
untuk maklumat lanjut.
Membuat Rujukan
Rujukan boleh dibuat dalam beberapa cara.
1. Dengan menggunakan pengendali sengkang terbalik pada pembolehubah, subrutin atau nilai. (Ini sangat berkesan
seperti & (alamat-bagi) operator dalam C.) Ini biasanya mencipta lain rujukan kepada a
pembolehubah, kerana sudah ada rujukan kepada pembolehubah dalam jadual simbol.
Tetapi rujukan jadual simbol mungkin hilang, dan anda masih mempunyai rujukan itu
garis miring ke belakang kembali. Berikut adalah beberapa contoh:
$scalarref = \$foo;
$arrayref = \@ARGV;
$hashref = \%ENV;
$coderef = \&pengendali;
$globref = \*foo;
Tidak mustahil untuk membuat rujukan sebenar kepada pemegang IO (failhandle atau dirhandle)
menggunakan pengendali garis miring ke belakang. Yang paling anda boleh dapatkan ialah rujukan kepada typeglob,
yang sebenarnya merupakan entri jadual simbol yang lengkap. Tetapi lihat penjelasan
*foo{THING} sintaks di bawah. Walau bagaimanapun, anda masih boleh menggunakan jenis glob dan globref sebagai
walaupun mereka adalah pemegang IO.
2. Rujukan kepada tatasusunan tanpa nama boleh dibuat menggunakan kurungan segi empat sama:
$arrayref = [1, 2, ['a', 'b', 'c']];
Di sini kami telah mencipta rujukan kepada tatasusunan tanpa nama bagi tiga elemen yang terakhir
elemen itu sendiri merujuk kepada tatasusunan tanpa nama yang lain bagi tiga elemen. (The
sintaks multidimensi yang diterangkan kemudian boleh digunakan untuk mengakses ini. Sebagai contoh,
selepas perkara di atas, "$arrayref->[2][1]" akan mempunyai nilai "b".)
Mengambil rujukan kepada senarai terhitung tidak sama dengan menggunakan segi empat sama
kurungan--sebaliknya ia sama seperti mencipta senarai rujukan!
@senarai = (\$a, \@b, \%c);
@senarai = \($a, @b, %c); # benda yang sama!
Sebagai kes khas, "\(@foo)" mengembalikan senarai rujukan kepada kandungan @foo, bukan
rujukan kepada @foo sendiri. Begitu juga untuk %foo, kecuali rujukan utama adalah kepada
salinan (kerana kekunci hanyalah rentetan daripada skalar penuh).
3. Rujukan kepada cincang tanpa nama boleh dibuat menggunakan kurungan kerinting:
$hashref = {
'Adam' => 'Hawa',
'Clyde' => 'Bonnie',
};
Komposer cincang dan tatasusunan tanpa nama seperti ini boleh dicampur secara bebas untuk menghasilkan sebagai
rumit struktur seperti yang anda mahu. Sintaks berbilang dimensi yang diterangkan di bawah
berfungsi untuk ini juga. Nilai di atas adalah literal, tetapi pembolehubah dan ungkapan
akan berfungsi dengan baik, kerana pengendali tugasan dalam Perl (walaupun dalam tempatan() or
saya()) ialah pernyataan boleh laku, bukan pengisytiharan masa kompilasi.
Kerana kurungan kerinting (braces) digunakan untuk beberapa perkara lain termasuk BLOCK,
anda mungkin kadangkala perlu menyahkekaburan pendakap pada permulaan pernyataan oleh
meletakkan "+" atau "kembali" di hadapan supaya Perl menyedari pendakap pembukaan tidak
memulakan BLOK. Nilai ekonomi dan mnemonik menggunakan kerinting dianggap berbaloi
kerumitan tambahan sekali-sekala ini.
Sebagai contoh, jika anda mahu fungsi membuat cincang baharu dan mengembalikan rujukan kepadanya,
anda mempunyai pilihan ini:
sub hashem { { @_ } } # secara senyap salah
sub hashem { +{ @_ } } # ok
sub hashem { return { @_ } } # ok
Sebaliknya, jika anda mahukan makna lain, anda boleh melakukan ini:
sub showem { { @_ } } # samar-samar (pada masa ini ok,
# tetapi mungkin berubah)
sub showem { {; @_ } } # okey
sub showem { { return @_ } } # ok
"+{" dan "{;" terkemuka sentiasa berfungsi untuk menyahkaburkan ungkapan yang bermaksud sama ada
rujukan HASH, atau BLOCK.
4. Rujukan kepada subrutin tanpa nama boleh dibuat dengan menggunakan "sub" tanpa a
nama kecil:
$coderef = sub { print "Boink!\n" };
Perhatikan titik bertitik. Kecuali kod di dalamnya tidak dilaksanakan serta-merta, "sub
{}" bukanlah satu pengisytiharan tetapi ia adalah pengendali, seperti "do{}" atau "eval{}".
(Walau bagaimanapun, tidak kira berapa kali anda melaksanakan baris tertentu itu (melainkan anda berada dalam
"eval("...")"), $coderef masih mempunyai rujukan kepada sama tanpa nama
subrutin.)
Subrutin tanpa nama bertindak sebagai penutup berkenaan dengan saya() pembolehubah, iaitu
pembolehubah boleh dilihat secara leksikal dalam skop semasa. Penutupan adalah tanggapan daripada
Dunia Lisp yang mengatakan jika anda mentakrifkan fungsi tanpa nama dalam leksikal tertentu
konteks, ia berpura-pura berjalan dalam konteks itu walaupun ia dipanggil di luar konteks.
Dalam istilah manusia, ini adalah cara yang lucu untuk menyampaikan hujah kepada subrutin apabila anda mentakrifkan
ia serta apabila anda memanggilnya. Ia berguna untuk menyediakan sedikit kod untuk dijalankan
kemudian, seperti panggilan balik. Anda juga boleh melakukan perkara berorientasikan objek dengannya, walaupun Perl
sudah menyediakan mekanisme berbeza untuk melakukannya--lihat perlobj.
Anda juga mungkin menganggap penutupan sebagai cara untuk menulis templat subrutin tanpa menggunakan
eval (). Berikut ialah contoh kecil cara penutupan berfungsi:
sub cetakan baharu {
$x saya = shift;
kembalikan sub { $y saya = shift; cetak "$x, $y!\n"; };
}
$h = newprint("Howdy");
$g = newprint("Salam");
# Masa berlalu...
&$h("dunia");
&$g("orang bumi");
Ini mencetak
Apa khabar, dunia!
Salam, warga bumi!
Ambil perhatian terutamanya bahawa $x terus merujuk kepada nilai yang dihantar cetakan baru()
walaupun "my $x" telah keluar dari skop pada masa subrutin tanpa nama dijalankan.
Itulah maksud penutupan.
Ini hanya terpakai kepada pembolehubah leksikal, dengan cara ini. Pembolehubah dinamik berterusan
bekerja sebagaimana mereka selalu bekerja. Penutupan bukanlah sesuatu yang kebanyakan pengaturcara Perl
perlu menyusahkan diri mereka untuk bermula.
5. Rujukan sering dikembalikan oleh subrutin khas yang dipanggil pembina. Perl
objek hanyalah rujukan kepada jenis objek khas yang kebetulan mengetahui yang mana
pakej yang dikaitkan dengannya. Pembina hanyalah subrutin khas yang tahu caranya
untuk mewujudkan persatuan itu. Mereka berbuat demikian dengan bermula dengan rujukan biasa, dan ia
kekal sebagai rujukan biasa walaupun ia juga menjadi objek. Pembina adalah
selalunya dinamakan "new()". awak boleh memanggil mereka secara tidak langsung:
$objref = new Doggie( Ekor => 'pendek', Telinga => 'panjang' );
Tetapi itu boleh menghasilkan sintaks samar-samar dalam kes tertentu, jadi selalunya lebih baik untuk digunakan
pendekatan penyeruan kaedah langsung:
$objref = Doggie->new(Ekor => 'pendek', Telinga => 'panjang');
gunakan Term::Cap;
$terminal = Term::Cap->Tgetent( { OSPEED => 9600 });
gunakan Tk;
$utama = MainWindow->new();
$menubar = $main->Frame(-relief => "dinaikkan",
-borderwidth => 2)
6. Rujukan jenis yang sesuai boleh wujud jika anda tidak merujuknya
dalam konteks yang menganggap ia wujud. Kerana kita tidak bercakap tentang penyahrujukan
namun, kami belum dapat menunjukkan sebarang contoh kepada anda.
7. Rujukan boleh dibuat dengan menggunakan sintaks khas, yang dikenali sebagai
sintaks *foo{THING}. *foo{THING} mengembalikan rujukan kepada slot THING dalam *foo (yang
ialah entri jadual simbol yang menyimpan semua yang dikenali sebagai foo).
$scalarref = *foo{SCALAR};
$arrayref = *ARGV{ARRAY};
$hashref = *ENV{HASH};
$coderef = *pengendali{CODE};
$ioref = *STDIN{IO};
$globref = *foo{GLOB};
$formatref = *foo{FORMAT};
$globname = *foo{NAME}; # "foo"
$pkgname = *foo{PAKEJ}; # "utama"
Kebanyakan daripada ini adalah penjelasan sendiri, tetapi *foo{IO} patut diberi perhatian khusus. Ia
mengembalikan pemegang IO, digunakan untuk pemegang fail ("terbuka" dalam perlfunc), soket ("soket"
dalam perlfunc dan "socketpair" dalam perlfunc), dan pemegang direktori ("opendir" dalam
perlfunc). Untuk keserasian dengan versi sebelumnya Perl, *foo{FILEHANDLE} ialah a
sinonim untuk *foo{IO}, walaupun ia ditamatkan pada 5.8.0. Jika amaran penamatan
berkuat kuasa, ia akan memberi amaran tentang penggunaannya.
*foo{THING} mengembalikan undef jika PERKARA tertentu itu belum digunakan lagi, kecuali dalam
kes skalar. *foo{SCALAR} mengembalikan rujukan kepada skalar tanpa nama jika $foo
belum digunakan lagi. Ini mungkin berubah dalam keluaran akan datang.
*foo{NAME} dan *foo{PACKAGE} adalah pengecualian, kerana mereka mengembalikan rentetan, sebaliknya
daripada rujukan. Ini mengembalikan pakej dan nama typeglob itu sendiri
daripada satu yang telah ditugaskan kepadanya. Jadi, selepas "*foo=*Foo::bar", *foo akan menjadi
"*Foo::bar" apabila digunakan sebagai rentetan, tetapi *foo{PACKAGE} dan *foo{NAME} akan terus
menghasilkan "utama" dan "foo", masing-masing.
*foo{IO} ialah alternatif kepada mekanisme *HANDLE yang diberikan dalam "Typeglobs and
Filehandles" dalam perldata untuk menghantar failhandles ke dalam atau keluar daripada subrutin, atau
menyimpan ke dalam struktur data yang lebih besar. Kelemahannya ialah ia tidak akan mencipta yang baharu
pemegang fail untuk anda. Kelebihannya ialah anda mempunyai risiko yang lebih rendah untuk melakukan clobbing lebih daripada
anda mahu dengan tugasan typeglob. (Ia masih menggabungkan fail dan direktori
mengendalikan, walaupun.) Walau bagaimanapun, jika anda menetapkan nilai masuk kepada skalar dan bukannya a
typeglob seperti yang kita lakukan dalam contoh di bawah, tiada risiko perkara itu berlaku.
percikan(*STDOUT); # melepasi seluruh glob
percikan(*STDOUT{IO}); # lulus kedua-dua fail dan pemegang dir
sub splutter {
$fh saya = shift;
print $fh "her um well a hmmm\n";
}
$rec = get_rec(*STDIN); # melepasi seluruh glob
$rec = get_rec(*STDIN{IO}); # lulus kedua-dua fail dan pemegang dir
sub get_rec {
$fh saya = shift;
pulangan skalar <$fh>;
}
Menggunakan Rujukan
Itu sahaja untuk membuat rujukan. Pada masa ini anda mungkin tidak sabar untuk mengetahui cara menggunakannya
rujukan untuk mendapatkan kembali data anda yang telah lama hilang. Terdapat beberapa kaedah asas.
1. Di mana-mana sahaja anda akan meletakkan pengecam (atau rantaian pengecam) sebagai sebahagian daripada pembolehubah atau
nama subrutin, anda boleh menggantikan pengecam dengan pembolehubah skalar mudah
mengandungi rujukan jenis yang betul:
$bar = $$scalarref;
push(@$arrayref, $nama fail);
$$arrayref[0] = "Januari";
$$hashref{"KEY"} = "VALUE";
&$coderef(1,2,3);
cetak $globref "output\n";
Adalah penting untuk memahami bahawa kita secara khusus tidak membatalkan rujukan $arrayref[0]
atau $hashref{"KEY"} di sana. Penyahrujukan pembolehubah skalar berlaku sebelum it
melakukan sebarang carian utama. Apa-apa yang lebih rumit daripada pembolehubah skalar mudah mesti
gunakan kaedah 2 atau 3 di bawah. Walau bagaimanapun, "skalar mudah" termasuk pengecam itu
sendiri menggunakan kaedah 1 secara rekursif. Oleh itu, cetakan berikut "howdy".
$refrefref = \\\"selamat sejahtera";
cetak $$$$refref;
2. Di mana-mana sahaja anda akan meletakkan pengecam (atau rantaian pengecam) sebagai sebahagian daripada pembolehubah atau
nama subrutin, anda boleh menggantikan pengecam dengan BLOCK yang mengembalikan rujukan
jenis yang betul. Dengan kata lain, contoh sebelumnya boleh ditulis seperti ini:
$bar = ${$scalarref};
push(@{$arrayref}, $nama fail);
${$arrayref}[0] = "Januari";
${$hashref}{"KEY"} = "VALUE";
&{$coderef}(1,2,3);
$globref->print("output\n"); # iff IO::Handle dimuatkan
Diakui, agak bodoh untuk menggunakan kerinting dalam kes ini, tetapi BLOCK boleh
mengandungi sebarang ungkapan arbitrari, khususnya, ungkapan berlangganan:
&{ $dispatch{$index} }(1,2,3); # panggilan rutin yang betul
Kerana dapat menghilangkan kerinting untuk kes mudah $$x, orang sering
membuat kesilapan melihat simbol dereferencing sebagai pengendali yang betul, dan tertanya-tanya
tentang keutamaan mereka. Jika begitu, anda boleh menggunakan tanda kurung sebagai gantinya
pendakap gigi. Itu bukan kesnya. Pertimbangkan perbezaan di bawah; kes 0 ialah tangan pendek
versi kes 1, tidak kes 2:
$$hashref{"KEY"} = "VALUE"; # KES 0
${$hashref}{"KEY"} = "VALUE"; # KES 1
${$hashref{"KEY"}} = "VALUE"; # KES 2
${$hashref->{"KEY"}} = "VALUE"; # KES 3
Kes 2 juga mengelirukan kerana anda mengakses pembolehubah yang dipanggil %hashref, bukan
membatalkan rujukan melalui $hashref kepada cincang yang mungkin merujuknya. Itu akan jadi
kes 3.
3. Panggilan subrutin dan carian elemen tatasusunan individu cukup kerap timbul sehingga ia
menjadi rumit untuk menggunakan kaedah 2. Sebagai bentuk gula sintaksis, contoh untuk
kaedah 2 boleh ditulis:
$arrayref->[0] = "Januari"; # Elemen tatasusunan
$hashref->{"KEY"} = "VALUE"; # Elemen cincang
$coderef->(1,2,3); # Panggilan subrutin
Bahagian kiri anak panah boleh berupa sebarang ungkapan yang mengembalikan rujukan, termasuk a
dereference sebelumnya. Ambil perhatian bahawa $array[$x] ialah tidak perkara yang sama seperti "$array->[$x]"
di sini:
$array[$x]->{"foo"}->[0] = "Januari";
Ini adalah salah satu kes yang kami nyatakan sebelum ini di mana rujukan boleh muncul
kewujudan apabila dalam konteks nilai. Sebelum penyataan ini, $array[$x] mungkin pernah
tidak ditentukan. Jika ya, ia ditakrifkan secara automatik dengan rujukan cincang supaya kita boleh
cari "{"foo"}" di dalamnya. Begitu juga "$array[$x]->{"foo"}" akan mendapat secara automatik
ditakrifkan dengan rujukan tatasusunan supaya kita boleh mencari "[0]" di dalamnya. Proses ini adalah
dipanggil autovivifikasi.
Satu perkara lagi di sini. Anak panah adalah pilihan antara kurungan subskrip, jadi anda boleh
kecilkan di atas ke
$array[$x]{"foo"}[0] = "Januari";
Yang, dalam kes merosot menggunakan hanya tatasusunan biasa, memberi anda
tatasusunan berbilang dimensi seperti C:
$skor[$x][$y][$z] += 42;
Baiklah, sebenarnya tidak seperti tatasusunan C. C tidak tahu cara mengembangkannya
tatasusunan atas permintaan. Perl lakukan.
4. Jika rujukan menjadi rujukan kepada objek, maka mungkin terdapat kaedah
untuk mengakses perkara yang dirujuk, dan anda mungkin harus berpegang pada kaedah tersebut
melainkan anda berada dalam pakej kelas yang mentakrifkan kaedah objek. Dalam kata lain,
bersikap baik, dan jangan melanggar enkapsulasi objek tanpa alasan yang sangat kukuh.
Perl tidak menguatkuasakan enkapsulasi. Kami bukan totalitarian di sini. Kami menjangkakan
beberapa kesopanan asas walaupun.
Menggunakan rentetan atau nombor sebagai rujukan menghasilkan rujukan simbolik, seperti yang dijelaskan di atas.
Menggunakan rujukan sebagai nombor menghasilkan integer yang mewakili lokasi storannya dalam
ingatan. Satu-satunya perkara yang berguna untuk dilakukan dengan ini ialah membandingkan dua rujukan
secara berangka untuk melihat sama ada mereka merujuk kepada lokasi yang sama.
if ($ref1 == $ref2) { # perbandingan angka murah rujukan
cetak "rujukan 1 dan 2 merujuk kepada perkara yang sama\n";
}
Menggunakan rujukan sebagai rentetan menghasilkan kedua-dua jenis rujukannya, termasuk sebarang pakej
berkat seperti yang diterangkan dalam perlobj, serta alamat berangka yang dinyatakan dalam hex. The
ref() operator hanya mengembalikan jenis perkara yang ditunjuk oleh rujukan, tanpa
alamat. Lihat "ref" dalam perlfunc untuk butiran dan contoh penggunaannya.
. memberkati() operator boleh digunakan untuk mengaitkan objek titik rujukan dengan a
pakej berfungsi sebagai kelas objek. Lihat perlobj.
Glob jenis boleh dinyahrujuk dengan cara yang sama dengan rujukan, kerana nyahrujukan
sintaks sentiasa menunjukkan jenis rujukan yang diingini. Jadi "${*foo}" dan "${\$foo}" kedua-duanya
menunjukkan pembolehubah skalar yang sama.
Berikut ialah helah untuk menginterpolasi panggilan subrutin ke dalam rentetan:
print "Sub saya kembali @{[mysub(1,2,3)]} masa itu.\n";
Cara ia berfungsi ialah apabila "@{...}" dilihat dalam rentetan petikan dua, ia adalah
dinilai sebagai satu blok. Blok mencipta rujukan kepada tatasusunan tanpa nama yang mengandungi
keputusan panggilan ke "mysub(1,2,3)". Jadi keseluruhan blok mengembalikan rujukan kepada an
tatasusunan, yang kemudiannya dinyahrujuk oleh "@{...}" dan melekat pada rentetan petikan dua kali.
Chicanery ini juga berguna untuk ungkapan sewenang-wenangnya:
cetak "Itu menghasilkan @{[$n + 5]} widget\n";
Begitu juga, ungkapan yang mengembalikan rujukan kepada skalar boleh dinyahrujuk melalui
"${...}". Oleh itu, ungkapan di atas boleh ditulis sebagai:
cetak "Itu menghasilkan ${\($n + 5)} widget\n";
Pekeliling Rujukan
Anda boleh membuat "rujukan bulat" dalam Perl, yang boleh menyebabkan kebocoran memori. A
rujukan pekeliling berlaku apabila dua rujukan mengandungi rujukan antara satu sama lain, seperti
ini:
$foo saya = {};
$bar saya = {foo => $foo};
$foo->{bar} = $bar;
Anda juga boleh membuat rujukan bulat dengan pembolehubah tunggal:
$foo saya;
$foo = \$foo;
Dalam kes ini, kiraan rujukan untuk pembolehubah tidak akan mencapai 0, dan rujukan
tidak akan pernah dikumpul sampah. Ini boleh menyebabkan kebocoran ingatan.
Oleh kerana objek dalam Perl dilaksanakan sebagai rujukan, adalah mungkin untuk mempunyai pekeliling
rujukan dengan objek juga. Bayangkan kelas TreeNode di mana setiap nod merujuknya
nod ibu bapa dan anak. Mana-mana nod dengan induk akan menjadi sebahagian daripada rujukan pekeliling.
Anda boleh memecahkan rujukan bulat dengan mencipta "rujukan lemah". Rujukan yang lemah tidak
tidak menambah kiraan rujukan untuk pembolehubah, yang bermaksud bahawa objek boleh keluar
skop dan dimusnahkan. Anda boleh melemahkan rujukan dengan fungsi "melemahkan" yang dieksport
oleh modul Skalar::Util.
Begini cara kita boleh menjadikan contoh pertama lebih selamat:
gunakan Scalar::Util 'melemahkan';
$foo saya = {};
$bar saya = {foo => $foo};
$foo->{bar} = $bar;
melemahkan $foo->{bar};
Rujukan daripada $foo kepada $bar telah dilemahkan. Apabila pembolehubah $bar keluar dari
skop, ia akan dikumpul sampah. Kali seterusnya anda melihat nilai
Kekunci "$foo->{bar}", ia akan menjadi "undef".
Tindakan ini pada jarak jauh boleh mengelirukan, jadi anda harus berhati-hati dengan penggunaan anda
melemahkan. Anda harus melemahkan rujukan dalam pembolehubah yang akan keluar dari skop pertama.
Dengan cara itu, pembolehubah hidup lebih lama akan mengandungi rujukan yang dijangkakan sehingga ia keluar
skop.
Simbolik rujukan
Kami mengatakan bahawa rujukan muncul seperti yang diperlukan jika ia tidak ditentukan, tetapi kami
tidak mengatakan apa yang berlaku jika nilai yang digunakan sebagai rujukan sudah ditakrifkan, tetapi tidak a
rujukan keras. Jika anda menggunakannya sebagai rujukan, ia akan dianggap sebagai rujukan simbolik.
Iaitu, nilai skalar diambil sebagai nama pembolehubah, bukannya a
pautan terus ke nilai (mungkin) tanpa nama.
Orang sering mengharapkan ia berfungsi seperti ini. Begitu juga.
$name = "foo";
$$nama = 1; # Set $foo
${$nama} = 2; # Set $foo
${$nama x 2} = 3; # Set $foofoo
$nama->[0] = 4; # Set $foo[0]
@$nama = (); # Membersihkan @foo
&$nama(); # Panggilan &foo()
$pack = "ITU";
${"${pack}::$name"} = 5; # Tetapkan $THAT::foo tanpa eval
Ini berkuasa, dan sedikit berbahaya, kerana ia mungkin untuk berniat (dengan sepenuhnya
ikhlas) untuk menggunakan rujukan keras, dan secara tidak sengaja menggunakan rujukan simbolik sebagai gantinya. Kepada
melindungi daripada itu, anda boleh katakan
gunakan 'ref' yang ketat;
dan kemudian hanya rujukan keras akan dibenarkan untuk seluruh blok yang disertakan. An
blok dalam boleh membalas permintaan itu dengan
tiada 'ref' yang ketat;
Hanya pembolehubah pakej (global, walaupun disetempatkan) kelihatan kepada rujukan simbolik.
Pembolehubah leksikal (diisytiharkan dengan saya()) tidak berada dalam jadual simbol, dan oleh itu tidak kelihatan kepada
mekanisme ini. Sebagai contoh:
nilai $ tempatan = 10;
$ref = "nilai";
{
$value saya = 20;
cetak $$ref;
}
Ini masih akan mencetak 10, bukan 20. Ingat itu tempatan() mempengaruhi pembolehubah pakej, yang
semuanya "global" kepada pakej.
Tidak begitu simbolik rujukan
Tanda kurung di sekeliling rujukan simbolik hanya boleh berfungsi untuk mengasingkan pengecam atau pembolehubah
nama daripada seluruh ungkapan, seperti yang selalu ada dalam rentetan. Untuk
contohnya,
$push = "pop on";
cetak "${push}over";
sentiasa bermaksud untuk mencetak "pop on over", walaupun push ialah perkataan terpelihara. Ini adalah
digeneralisasikan untuk berfungsi sama tanpa tanda petikan berganda yang disertakan, supaya
cetak ${push} . "over";
dan malah
cetak ${ push } . "over";
akan mempunyai kesan yang sama. Konstruk ini ialah tidak dianggap sebagai rujukan simbolik
apabila anda menggunakan rujukan ketat:
gunakan 'ref' yang ketat;
${ kata depan }; # Okay, bermakna $bareword.
${ "kata kosong" }; # Ralat, rujukan simbolik.
Begitu juga, kerana semua langganan yang dilakukan menggunakan perkataan tunggal, peraturan yang sama
digunakan pada mana-mana kata kosong yang digunakan untuk melanggan cincang. Jadi sekarang, bukannya menulis
$array{ "aaa" }{ "bbb" }{ "ccc" }
anda boleh menulis sahaja
$array{ aaa }{ bbb }{ ccc }
dan jangan risau sama ada subskrip adalah perkataan terpelihara. Dalam kejadian yang jarang berlaku bahawa anda
ingin melakukan sesuatu seperti
$array{ shift }
anda boleh memaksa tafsiran sebagai perkataan terpelihara dengan menambah apa-apa sahaja yang menjadikannya lebih daripada
kata-kata kasar:
$array{ shift() }
$array{ +shift }
$array{ shift @_ }
Pragma "menggunakan amaran" atau -w suis akan memberi amaran kepada anda jika ia mentafsir perkataan terpelihara
sebagai rentetan. Tetapi ia tidak lagi akan memberi amaran kepada anda tentang menggunakan perkataan huruf kecil, kerana
rentetan dipetik dengan berkesan.
Pseudo-hashes: Menggunakan an pelbagai as a hash
Pseudo-hashes telah dialih keluar daripada Perl. Pragma 'medan' masih tersedia.
fungsi Templates
Seperti yang dijelaskan di atas, fungsi tanpa nama dengan akses kepada pembolehubah leksikal yang boleh dilihat
apabila fungsi itu disusun, mencipta penutupan. Ia mengekalkan akses kepada pembolehubah tersebut
walaupun ia tidak dijalankan sehingga kemudian, seperti dalam pengendali isyarat atau panggilan balik Tk.
Menggunakan penutupan sebagai templat fungsi membolehkan kami menjana banyak fungsi yang bertindak
serupa. Katakan anda mahukan fungsi yang dinamakan sempena warna yang menjana fon HTML
perubahan untuk pelbagai warna:
cetak "Jadilah ", merah("berhati-hati"), "dengan itu ", hijau("cahaya");
. merah() and hijau() fungsi akan serupa. Untuk membuat ini, kami akan menetapkan penutupan
kepada typeglob nama fungsi yang kami cuba bina.
@colors = qw(merah biru hijau kuning jingga ungu ungu);
untuk $nama saya (@warna) {
tiada 'ref' yang ketat; # benarkan manipulasi jadual simbol
*$nama = *{uc $name} = sub { " @_ " };
}
Kini semua fungsi yang berbeza itu kelihatan wujud secara bebas. Anda boleh menghubungi merah(),
MERAH(), biru(), BIRU(), hijau(), dsb. Teknik ini menjimatkan masa penyusunan dan memori
gunakan, dan juga kurang terdedah kepada ralat, kerana semakan sintaks berlaku pada masa penyusunan. ia adalah
kritikal bahawa mana-mana pembolehubah dalam subrutin tanpa nama menjadi leksikal untuk mencipta a
penutupan yang betul. Itulah sebab untuk "saya" pada pembolehubah lelaran gelung.
Ini adalah satu-satunya tempat yang memberikan prototaip kepada penutupan sangat masuk akal. Jika
anda ingin mengenakan konteks skalar pada hujah fungsi ini (mungkin bukan a
idea yang bijak untuk contoh khusus ini), anda boleh menulisnya dengan cara ini sebaliknya:
*$nama = sub ($) { " $_[0] " };
Walau bagaimanapun, memandangkan semakan prototaip berlaku pada masa penyusunan, tugasan di atas berlaku
terlambat untuk banyak digunakan. Anda boleh menangani perkara ini dengan meletakkan keseluruhan gelung
tugasan dalam blok BEGIN, memaksa ia berlaku semasa penyusunan.
Akses kepada leksikal yang berubah mengikut masa--seperti yang terdapat dalam gelung "untuk" di atas, pada asasnya
alias kepada elemen daripada skop leksikal sekeliling-- hanya berfungsi dengan subs tanpa nama,
bukan dengan subrutin yang dinamakan. Secara umumnya, subrutin yang dinamakan tidak bersarang dengan betul dan
hendaklah hanya diisytiharkan dalam skop pakej utama.
Ini kerana subrutin yang dinamakan dicipta pada masa penyusunan jadi pembolehubah leksikalnya
diberikan kepada leksikal induk daripada pelaksanaan pertama blok induk. Sekiranya
skop induk dimasukkan kali kedua, leksikalnya dicipta semula, manakala bersarang
subs masih merujuk yang lama.
Subrutin tanpa nama dapat menangkap setiap kali anda melaksanakan pengendali "sub", sebagaimana adanya
dicipta dengan cepat. Jika anda sudah biasa menggunakan subrutin bersarang dalam pengaturcaraan lain
bahasa dengan pembolehubah peribadi mereka sendiri, anda perlu berusaha sedikit dalam Perl. The
pengekodan intuitif bagi jenis perkara ini menimbulkan amaran misteri tentang "tidak akan kekal
dikongsi" disebabkan oleh sebab yang dijelaskan di atas. Contohnya, ini tidak akan berfungsi:
sub luar {
$x saya = $_[0] + 35;
sub inner { return $x * 19 } # SALAH
pulangkan $x + inner();
}
Penyelesaian adalah yang berikut:
sub luar {
$x saya = $_[0] + 35;
tempatan *dalam = sub { return $x * 19 };
pulangkan $x + inner();
}
Sekarang dalaman() hanya boleh dipanggil dari dalam luar(), kerana tugasan sementara
daripada subrutin tanpa nama. Tetapi apabila ia berlaku, ia mempunyai akses biasa kepada leksikal
pembolehubah $x daripada skop luar() pada masa luar dipanggil.
Ini mempunyai kesan menarik untuk mencipta fungsi setempat kepada fungsi lain,
sesuatu yang biasanya tidak disokong dalam Perl.
BERKHATAN :
Anda tidak boleh (berguna) menggunakan rujukan sebagai kunci kepada cincangan. Ia akan ditukar menjadi a
tali:
$x{ \$a } = $a;
Jika anda cuba menyahrujuk kunci, ia tidak akan melakukan penyahrujukan yang sukar, dan anda tidak akan melakukannya
mencapai apa yang anda cuba. Anda mungkin mahu melakukan sesuatu yang lebih seperti itu
$r = \@a;
$x{ $r } = $r;
Dan kemudian sekurang-kurangnya anda boleh menggunakan nilai (), yang akan menjadi rujukan sebenar, bukannya
kunci (), yang tidak akan.
Modul Tie::RefHash standard menyediakan penyelesaian yang mudah untuk ini.
Postfix Dereference Syntax
Bermula dalam v5.20.0, sintaks postfix untuk menggunakan rujukan tersedia. Ia berkelakuan sebagai
diterangkan dalam "Menggunakan Rujukan", tetapi bukannya sigil awalan, sigil-dan- postfixed
bintang digunakan.
Sebagai contoh:
$r = \@a;
@b = $r->@*; # bersamaan dengan @$r atau @{ $r }
$r = [ 1, [ 2, 3 ], 4 ];
$r->[1]->@*; # bersamaan dengan @{ $r->[1] }
Sintaks ini mesti didayakan dengan "gunakan ciri 'postderef'". Ia adalah percubaan, dan akan
memberi amaran secara lalai melainkan "tiada amaran 'percubaan::postderef'" berkuat kuasa.
Penyahrujukan postfix harus berfungsi dalam semua keadaan di mana penyahrujukan blok (circumfix).
bekerja, dan harus setara sepenuhnya. Sintaks ini membolehkan penyahrujukan ditulis
dan baca sepenuhnya dari kiri ke kanan. Kesetaraan berikut ditakrifkan:
$sref->$*; # sama seperti ${ $sref }
$aref->@*; # sama seperti @{ $aref }
$aref->$#*; # sama seperti $#{ $aref }
$href->%*; # sama seperti %{ $href }
$cref->&*; # sama seperti &{ $cref }
$gref->**; # sama seperti *{ $gref }
Ambil perhatian terutamanya bahawa "$cref->&*" ialah tidak bersamaan dengan "$cref->()", dan boleh berkhidmat berbeza
tujuan.
Elemen glob boleh diekstrak melalui ciri dereferencing postfix:
$gref->*{SCALAR}; # sama seperti *{ $gref }{SCALAR}
Tatasusunan Postfix dan penyahrujukan skalar boleh digunakan dalam interpolasi rentetan (petikan berganda
atau pengendali "qq"), tetapi hanya jika ciri "postderef_qq" tambahan didayakan.
Postfix Rujukan Menghirup
Potongan nilai tatasusunan dan cincang juga boleh diambil dengan tatatanda penyahrujukan postfix,
dengan persamaan berikut:
$aref->@[ ... ]; # sama seperti @$aref[ ... ]
$href->@{ ... }; # sama seperti @$href{ ... }
Potongan pasangan kunci/nilai Postfix, ditambah dalam 5.20.0 dan didokumenkan dalam Key/Value Hash
Bahagian hirisan perldata, juga berkelakuan seperti yang diharapkan:
$aref->%[ ... ]; # sama seperti %$aref[ ... ]
$href->%{ ... }; # sama seperti %$href{ ... }
Seperti tatasusunan postfix, penyahrujukan hirisan nilai postfix boleh digunakan dalam interpolasi
rentetan (petikan berganda atau pengendali "qq"), tetapi hanya jika tambahan "postderef_qq"
ciri didayakan.
Menugaskan kepada Rujukan
Bermula dalam v5.22.0, pengendali rujukan boleh diberikan kepada. Ia melaksanakan satu
operasi aliasing, supaya nama pembolehubah yang dirujuk di sebelah kiri menjadi
alias untuk perkara yang dirujuk di sebelah kanan:
\$a = \$b; # $a dan $b kini menunjuk kepada skalar yang sama
\&foo = \&bar; # foo() kini bermaksud bar()
Sintaks ini mesti didayakan dengan "menggunakan ciri 'refaliasing'". Ia adalah percubaan, dan
akan memberi amaran secara lalai melainkan "tiada amaran 'percubaan::refaliasing'" berkuat kuasa.
Borang-borang ini boleh diberikan kepada, dan menyebabkan bahagian kanan dinilai dalam skalar
konteks:
\$skalar
\@tatasusunan
\% hash
\&sub
\my $scalar
\my @array
\my %hash
\nyatakan $scalar # atau @array, dsb.
\$scalar # kami dsb.
\local $scalar # dsb.
\local $scalar # kami dsb.
\$some_array[$index]
\$some_hash{$key}
\local $some_array[$index]
\local $some_hash{$key}
syarat ? \$ini : \$itu[0] # dsb.
Operasi menghiris dan kurungan menyebabkan bahagian sebelah kanan dinilai dalam senarai
konteks:
\@array[5..7]
(\@array[5..7])
\(@array[5..7])
\@hash{'foo','bar'}
(\@hash{'foo','bar'})
\(@hash{'foo','bar'})
(\$scalar)
\($scalar)
\($skalar saya)
\my($scalar)
(\@array)
(\%hash)
(\&sub)
\(&sub)
\($foo, @bar, %baz)
(\$foo, \@bar, \%baz)
Setiap elemen di sebelah kanan mestilah merujuk kepada datum jenis yang betul.
Tanda kurung serta-merta mengelilingi tatasusunan (dan mungkin juga
"my"/"state"/"our"/"local") akan menjadikan setiap elemen tatasusunan sebagai alias kepada
skalar yang sepadan dirujuk di sebelah kanan:
\(@a) = \(@b); # @a dan @b kini mempunyai elemen yang sama
\my(@a) = \(@b); # begitu juga
\(saya @a) = \(@b); # begitu juga
tolak @a, 3; # tetapi sekarang @a mempunyai elemen tambahan yang kekurangan @b
\(@a) = (\$a, \$b, \$c); # @a kini mengandungi $a, $b dan $c
Menggabungkan borang itu dengan "tempatan" dan meletakkan tanda kurung serta-merta di sekeliling cincang adalah
dilarang (kerana tidak jelas apa yang harus mereka lakukan):
\local(@array) = foo(); # SALAH
\(% hash) = bar(); # salah
Tugasan kepada rujukan dan bukan rujukan boleh digabungkan dalam senarai dan bersyarat
ungkapan ternary, selagi nilai di sebelah kanan adalah jenis yang sesuai untuk
setiap elemen di sebelah kiri, walaupun ini mungkin menyebabkan kod dikaburkan:
(my $tom, \my $dick, \my @harry) = (\1, \2, [1..3]);
# $tom kini \1
# $dick kini 2 (baca sahaja)
# @harry ialah (1,2,3)
$type saya = ref $thingy;
($type ? $type == 'ARRAY' ? \@foo : \$bar : $baz) = $thingy;
Gelung "foreach" juga boleh mengambil pembina rujukan untuk pembolehubah gelungnya, walaupun
sintaks terhad kepada salah satu daripada yang berikut, dengan pilihan "saya", "keadaan" atau "kami" selepasnya
garis miring ke belakang:
\$s
\@a
\%h
\&c
Tiada kurungan dibenarkan. Ciri ini amat berguna untuk tatasusunan-tatasusunan,
atau tatasusunan-cincang:
foreach \my @a (@array_of_arrays) {
frobnicate($a[0], $a[-1]);
}
foreach \my %h (@array_of_hashes) {
$h{gelastik}++ jika $h{type} == 'lucu';
}
CAVEAT: Aliasing tidak berfungsi dengan betul dengan penutupan. Jika anda cuba untuk alias leksikal
pembolehubah daripada subrutin dalaman atau "eval", aliasing hanya akan kelihatan dalam
sub dalam itu, dan tidak akan menjejaskan subrutin luar tempat pembolehubah diisytiharkan.
Tingkah laku pelik ini tertakluk kepada perubahan.
Gunakan perlref dalam talian menggunakan perkhidmatan onworks.net