Provided by:
manpages-pl_20060617-3_all 
NAZWA
perlref - odwolania i zagniedone struktury danych w Perlu
UWAGA
To jest pelna dokumentacja dotyczca wszelkich aspektow odwola.
Krotszy, wprowadzajcy wstp to najistotniejszych cech znajdziesz w
podrczniku perlreftut(1).
OPIS
Przed wersj 5 Perla przedstawianie zloonych struktur danych bylo
trudne, gdy wszystkie odwolania musialy by symboliczne -- a nawet wtedy
ciko bylo odnosi si do zmiennej zamiast do pozycji w tablicy symboli.
Obecnie Perl nie tylko ulatwia poslugiwanie si symbolicznymi
odwolaniami do zmiennych, ale take pozwala na uycie "stalych" odwola
(hard references) do dowolnego kawalka danych lub kodu. Stale dowizanie
moe by przechowywane w dowolnym skalarze. Poniewa tablice i tablice
asocjacyjne (hasze) zawieraj skalary, to moesz teraz latwo budowa
tablice tablic, tablice haszy, hasze tablic, tablice haszy funkcji i
tak dalej.
Odwolania stale s sprytne -- utrzymuj za ciebie liczniki odwola,
automatycznie zwalniajc rzecz, do ktorej odnosi si odwolanie, jeli jej
licznik odwola zejdzie do zera. (Uwaga: liczniki odwola dla wartoci w
strukturach danych odnoszcych si do samych na siebie (self-referential)
lub strukturach cyklicznych mog nie schodzi do zera bez pewnej drobnej
pomocy; patrz sekcja Two-Phased Garbage Collection w podrczniku
perlobj(1), zawierajca bardziej szczegolowy opis.) Jeli taka rzecz
jest obiektem, to obiekt jest niszczony. Wicej o obiektach znajdziesz w
podrczniku perlobj(1). (W pewnym sensie, wszystko w Perlu jest
obiektem, ale zwykle rezerwujemy to slowo dla odwola do obiektow, ktore
zostaly oficjalnie "poblogoslawione" ("blessed") [tj.zakwalifikowane
jako obiekty] w pakiecie klasy.)
Odwolania symboliczne s nazwami zmiennych lub innych obiektow; zupelnie
tak jak dowizania symboliczne (symbolic links) w uniksowym systemie
plikow zawieraj wylcznie nazw pliku. Notacja *glob jest rodzajem
odwolania symbolicznego. (Odwolania symboliczne nazywane s czasami
"soft references" [odwolaniami mikkimi, w przeciwiestwie do "hard
r."-"twardych"], ale prosz nie nazywaj ich tak; odwolania s
wystarczajco zbijajce z pantalyku bez zbdnych synonimow.)
W przeciwiestwie do nich, odwolania stale przypominaj dowizania stale
(hard links) uniksowego systemu plikow: slu do udostpniania obiektu bez
zwracania uwagi na to, jaka jest jego (inna) nazwa. Tam, gdzie uyto
slowa "odwolanie" bez przymiotnika, jak w poniszym akapicie, mowi si
zwykle o odwolaniu stalym.
W Perlu odwolania s latwe w uyciu. Jest tylko jedna nadrzdna zasada:
Perl nie wykonuje niejawnego odwolywania bd dereferowania odwola.
[Dereferencing: odniesienie si z powrotem do obiektu, rzeczy na ktor
wskazuje odwolanie]. Gdy skalar przechowuje odwolanie, to zawsze
zachowuje si jak zwykly skalar. Nie zaczyna magicznie by tablic,
haszem czy procedur; musisz wprost nakaza takie zachowanie, wykonujc
dereferencj.
Tworzenie odwo/l/la
Odwolania mog by tworzone na kilka sposobow.
1. Przez zastosowanie operatora odwroconego ukonika do zmiennej,
procedury lub wartoci. (Dziala to bardzo podobnie do operatora &
(zwracajcego adres) w jzyku C.) Zauwa, e konstrukcja ta tworzy
KOLEJNE odwolanie do zmiennej, gdy w tablicy symboli istnieje ju
odwolanie do tej zmiennej. Jednak odwolanie z tablicy symboli moe
znikn, a nadal bdziesz mie odwolanie, ktore zwrocil odwrocony
ukonik. Oto kilka przykladow:
$scalarref = \$foo;
$arrayref = \@ARGV;
$hashref = \%ENV;
$coderef = \&handler;
$globref = \*foo;
Przy uyciu operatora odwroconego ukonika nie jest moliwe utworzenie
prawdziwego odwolania do uchwytu IO (uchwytu pliku lub katalogu).
Moesz co najwyej uzyska odwolanie do typeglob bdcego faktycznie
pelnym wpisem w tablicy symboli. (Przeczytaj jednak poniej
objanienie skladni *foo{CO}.) Mimo to, moesz nadal uywa typeglob i
odwola do nich jakby byly one uchwytami IO.
2. Odwolanie do anonimowej tablicy mona stworzy poslugujc si nawiasami
kwadratowymi:
$arrayref = [1, 2, ['a', 'b', 'c']];
Utworzylimy odwolanie do anonimowej tablicy trzech elementow,
ktorej ostatni element jest z kolei odwolaniem do innej anonimowej
tablicy trzech elementow. (Dostp do niej umoliwi opisana dalej
skladnia tablic wielowymiarowych. Na przyklad, dla powyszego
przykladu $arrayref->[2][1] zwraca warto "b".)
Zauwa, e stworzenie odwolania do listy wyliczanej nie jest tym
samym, co uycie nawiasow kwadratowych. Jest to natomiast tym samym,
co stworzenie listy odwola!
@list = (\$a, \@b, \%c);
@list = \($a, @b, %c); # to samo!
W przypadku szczegolnym, \(@foo) zwraca list odwola do zawartoci
@foo, nie za odwolanie do samej @foo. Podobnie jest dla %foo, z
wyjtkiem tego, e odwolania-klucze odnosz si do kopii (gdy klucze s
lacuchami znakowymi, a nie dowolnymi skalarami).
3. Odwolanie do anonimowej tablicy asocjacyjnej (hasza) mona utworzy
uywajc nawiasow klamrowych:
$hashref = {
'Adam' => 'Ewa',
'Clyde' => 'Bonnie',
};
Powysze konstruktory anonimowych haszy i tablic mona swobodnie
lczy. Umoliwia to otrzymywanie dowolnie skomplikowanych struktur.
Opisana skladnia wielowymiarowych tablic/haszy dziala take dla
nich. Wartoci w powyszym przykladzie byly literalami, ale rownie
dobrze moglyby by zmiennymi czy wyraeniami, gdy perlowe operatory
przypisania (nawet wewntrz local() czy my()) s wykonywalnymi
instrukcjami, a nie jedynie deklaracjami dla fazy kompilacji.
Poniewa nawiasy klamrowe slu do kilku innych rzeczy, a take do
tworzenia BLOKow, moesz by czasem zmuszony do uniknicia
dwuznacznoci tych nawiasow na pocztku instrukcji. Wystarczy wowczas
umieszczenie przed nimi + lub return, by Perl zorientowal si, e
otwierajcy nawias klamrowy nie rozpoczyna BLOKu. Oszczdno i zalety
mnemoniczne uycia nawiasow klamrowych warte s takiego sporadycznego
zamieszania.
Na przyklad, jeli chcialby, by funkcja tworzyla nowy hasz i
zwracala odwolanie do niego, to masz takie moliwoci:
sub hashem { { @_ } } # le, ale bez komunikatu o bldzie
sub hashem { +{ @_ } } # ok
sub hashem { return { @_ } } # ok
Z drugiej strony, jeli chcesz drugiego znaczenia nawiasow (blok),
zrob tak:
sub showem { { @_ } } # dwuznaczne (obecnie ok, ale moe si zmieni)
sub showem { {; @_ } } # ok
sub showem { { return @_ } } # ok
Zwro uwag, e pocztkowe +{ i {; zawsze slu do wykluczenia
dwuznacznoci wyraenia, aby znaczylo albo odwolanie do HASZa albo
BLOK.
4. Mona utworzy odwolanie do anonimowej procedury uywajc sub bez nazwy
procedury:
$coderef = sub { print "Bums!\n" };
Zwro uwag na obecno rednika. Poza faktem, e wewntrzny kod nie jest
wykonywany natychmiast, sub {} jest bardziej operatorem ni
deklaracj, podobnie zreszt jak do{} czy eval{}. (Jednak,
niezalenie od tego, ile razy wykonasz powysz lini (chyba e jeste
wewntrz eval("...")), $coderef wci bdzie zawiera odwolanie do TEJ
SAMEJ anonimowej procedury.)
Procedury anonimowe dzialaj jak zamknicia (closures) w odniesieniu
do zmiennych my(), to znaczy, zmiennych widocznych leksykalnie w
biecym zakresie. Zamknicie jest pojciem ze wiata Lispa, mowicym, e
jeli zdefiniujesz anonimow funkcj w konkretnym kontekcie
leksykalnym, to bdzie ona dziala w tym kontekcie nawet jeli zostala
wywolana poza nim.
Mowic po ludzku, jest to zabawny sposob przesylania argumentow do
procedury zarowno gdy j definiujesz jak i wtedy gdy j wywolujesz.
Przydaje si to do tworzenia malych fragmentow kodu do poniejszego
uruchamiania, jak np. wywolania wsteczne (callbacks). Przy ich
pomocy moesz robi nawet rzeczy zorientowane obiektowo, cho Perl
zapewnia ju odmienny mechanizm operowania obiektami --patrz
podrcznik perlobj(1).
Moesz rownie myle o zamkniciach jak o sposobie pisania szablonow
bez uywania eval. (Faktycznie, w wersji 5.000, eval bylo jedyn
metod uzyskania zamkni. Jeli poslugujesz si zamkniciami, moesz
potrzebowa "require 5.001".)
A to maly przyklad tego, jak dzialaj zamknicia:
sub newprint {
my $x = shift;
return sub { my $y = shift; print "$x, $y!\n"; };
}
$h = newprint("Howdy");
$g = newprint("Greetings");
# czas mija...
&$h("world");
&$g("earthlings");
Drukuje to
Howdy, world!
Greetings, earthlings!
Zwro uwag szczegolnie na to, e $x nadal odnosi si do wartoci
przeslanej do newprint(), mimo e zmienna "my $x" pozornie wyszla
poza swoj zakres, w momencie gdy wywolano anonimow procedur. O to
wlanie chodzi w zamkniciu.
Przy okazji: odnosi si do tylko do zmiennych leksykalnych. Zmienne
dynamiczne dzialaj nadal tak jak zawsze. Zamknicie nie jest czym, o
co musialaby si martwi wikszo programistow Perla.
5. Odwolania czsto zwracane s przez specjalne procedury zwane
konstruktorami. Obiekty w Perlu s po prostu odwolaniami do
specjalnego rodzaju obiektu, ktory wie z ktorym pakietem jest
zwizany. Konstruktory s specjalnymi procedurami, ktore wiedz jak
utworzy to powizanie. Robi to zaczynajc od zwyklego odwolania, i
pozostaje ono zwyklym odwolaniem nawet wtedy gdy jest rownoczenie
obiektem. Konstuktory czsto nazywane s new() i wywolywane nie
wprost:
$objref = new Psisko (Ogon => 'krotki', Uszy => 'dlugie');
Ale nie musz by:
$objref = Psisko->new(Ogon => 'krotki', Uszy => 'dlugie');
use Term::Cap;
$terminal = Term::Cap->Tgetent( { OSPEED => 9600 });
use Tk;
$main = MainWindow->new();
$menubar = $main->Frame(-relief => "raised",
-borderwidth => 2)
6. Odwolania odpowiedniego typu mog by powolywane do istnienia jeli
dereferencjonujesz je w kontekcie zakladajcym, e istniej. Poniewa
jeszcze nie mowilimy o dereferencji, nie moemy na razie pokaza
przykladow.
7. Odwolanie moe by utworzone przy pomocy specjalnej skladni, uroczo
zwanej skladni *foo{CO}. *foo{CO} zwraca odwolanie do przegrodki
CO w *foo (ktore jest pozycj w tablicy symboli przechowujc wszystko
znane jako foo.)
$scalarref = *foo{SCALAR};
$arrayref = *ARGV{ARRAY};
$hashref = *ENV{HASH};
$coderef = *handler{CODE};
$ioref = *STDIN{IO};
$globref = *foo{GLOB};
Wszystkie powysze wyraenia s oczywiste, z wyjtkiem *foo{IO}.
Zwraca ono uchwyt IO, uywany jako uchwyt pliku (patrz opis open w
podrczniku perlfunc(1)), gniazdo (opis socket oraz socketpair w
perlfunc(1)) lub uchwyt katalogu (opendir w perlfunc(1)). Dla
zgodnoci z poprzednimi wersjami Perla, *foo{UCHWYTPLIKU} jest
synonimem *foo{IO}.
*foo{CO} zwraca undef jeli dane CO jeszcze nie bylo uywane, z
wyjtkiem dla skalarow. Jeli nie uywano jeszcze $foo, *foo{SKALAR}
zwraca odwolanie do anonimowego skalara. W przyszlych wersjach moe
si to zmieni.
*foo{IO} jest alternatyw dla mechanizmu \*UCHWYTU opisanego w
sekcji Typeglobs and Filehandles podrcznika perldata(1), a slucego
do przesylania uchwytow plikow do i z procedur lub przechowywania w
wikszych strukturach danych. Jego wad jest to, e nie utworzy za
Ciebie nowego uchwytu pliku. Zalet za, e nie ryzykujesz wicej ni
zamierzale przy przypisaniem typeglob, cho jeli wykonasz
przypisanie do skalara zamiast do typeglob, to te dobrze.
splutter(*STDOUT);
splutter(*STDOUT{IO});
sub splutter {
my $fh = shift;
print $fh "her um well a hmmm\n";
}
$rec = get_rec(*STDIN);
$rec = get_rec(*STDIN{IO});
sub get_rec {
my $fh = shift;
return scalar <$fh>;
}
Pos/l/lugiwanie si odwo/l/laniami
To tyle o tworzeniu odwola. Teraz pewnie nie moesz si doczeka wiedzy
jak poslugiwa si odwolaniami, by moc wroci do swych lecych odlogiem
danych. Oto kilka podstawowych sposobow.
1. Wszdzie, gdzie postawilby identyfikator (lub lacuch
identyfikatorow) jako cz nazwy zmiennej czy procedury, moesz zastpi
identyfikator prost zmienn skalarn zawierajc odwolanie poprawnego
typu:
$bar = $$scalarref;
push(@$arrayref, $nazwapliku);
$$arrayref[0] = "stycze";
$$hashref{"KLUCZ"} = "WARTO";
&$coderef(1,2,3);
print $globref "wynik\n";
Wane jest, by zrozumie, e nie NIE wykonujemy tu specjalnie
dereferencji $arrayref[0] czy $hashref{"KLUCZ"}. Dereferencja
zmiennej skalarnej odbywa si PRZED przeszukaniem klucza (indeksu
tablicy). Wszystko bardziej skomplikowane ni dereferencja prostej
zmiennej skalarnej wymaga uycia niej opisanych metod 2 lub 3.
Jednak okrelenie "prosty skalar" obejmuje te identyfikator, ktory
sam uywa rekurencyjnie metody 1. Zatem ponisze drukuje "witaj".
$refrefref = \\\"witaj";
print $$$$refrefref;
2. Wszdzie, gdzie postawilby identyfikator (lub lacuch
identyfikatorow) jako cz nazwy zmiennej czy procedury, moesz zastpi
identyfikator BLOKiem zwracajcym odwolanie poprawnego typu. Inaczej
mowic, poprzednie przyklady mog zosta zapisane tak:
$bar = ${$scalarref};
push(@{$arrayref}, $nazwapliku);
${$arrayref}[0] = "stycze";
${$hashref}{"KLUCZ"} = "WARTO";
&{$coderef}(1,2,3);
$globref->print("wynik\n"); # jeli zaladowano IO::Handle
Niewtpliwie, uycie nawiasow klamrowych w tym przypadku nie jest
zbyt mdre, ale BLOK moe zawiera dowolne wyraenie, w szczegolnoci
wyraenia indeksowane:
&{ $dispatch{$index} }(1,2,3); # wywolaj wlaciw obslug
Z powodu moliwoci pomijania nawiasow klamrowych dla prostych
przypadkow $$x, ludzie czsto popelniaj bld postrzegania symboli
dereferencji jako prawdziwych operatorow i zastanawiaj si nad ich
priorytetem. Gdyby nimi byly, moglby uywa zwyklych nawiasow
zamiast klamrowych. Tak jednak nie jest. Rozwa ponisz ronic:
przypadek 0 jest skrocon wersj przypadku 1, NIE przypadku 2:
$$hashref{"KLUCZ"} = "WARTO"; # przypadek 0
${$hashref}{"KLUCZ"} = "WARTO"; # przypadek 1
${$hashref{"KLUCZ"}} = "WARTO"; # przypadek 2
${$hashref->{"KLUCZ"}} = "WARTO"; # przypadek 3
Przypadek 2 jest rownie mylcy, gdy odnosi si do zmiennej o nazwie
%hashref, nie za dereferencjonuje poprzez $hashref hasza, na ktory
wydawaloby si wskazuje skalar. To robi przypadek 3.
3. Wywolania procedur i poszukiwanie poszczegolnych elementow tablic
pojawiaj si wystarczajco czsto, by zastosowanie do nich metody 2
stalo si niewygodne. Jako form "oslodzenia skladni", przyklady z
metody 2 mona zapisa:
$arrayref->[0] = "stycze"; # element tablicy
$hashref->{"KLUCZ"} = "WARTO"; # element hasza
$coderef->(1,2,3); # wywolanie procedury
Lewa strona strzalki moe by dowolnym wyraeniem zwracajcym
odwolanie, lcznie z uprzedni dereferencj. [Ulatwia to operowanie
odwolaniami do zmiennych zawierajcych kolejne odwolania, jak
poniej]. Zauwa, e $array[$x] NIE jest tu tym samym co
$array->[$x]:
$array[$x]->{"foo"}->[0] = "stycze";
Jest to jeden z przypadkow wspomnianych wczeniej, gdzie odwolania
zaistniej, gdy zostan uyte w kontekcie l-wartoci. Przed t
instrukcj, element $array[$x] mogl by niezdefiniowany. W takim
przypadku, jest on definiowany automatycznie z nadaniem mu wartoci
-- odwolania do hasza, tak e moemy poszukiwa w haszu elementu o
kluczu "foo". Podobnie klucz $array[$x]->{"foo"} zostanie
automatycznie zdefiniowany z rownoczesnym nadaniem wartoci --
odwolania do tablicy, zatem bdzie mona w niej odnale [0]. Proces
ten zwany jest autovivification (automatyczne oywianie).
Jeszcze jedno. POMIDZY indeksami umieszczonymi w nawiasach
klamrowych strzalka jest opcjonalna, zatem moemy skroci powyszy
zapis do:
$array[$x]{"foo"}[0] = "stycze";
Co, w szczegolnym przypadku dzialania tylko na zwyklych tablicach,
daje tablice wielowymiarowe z zapisem jak w C:
$score[$x][$y][$z] += 42;
No dobrze, tak naprawd, nie calkiem jak tablice w C. C nie wie, jak
poszerza tablice na danie. Perl to potrafi.
4. Jeeli odwolanie jest odwolaniem do obiektu, to prawdopodobnie
istniej metody dostpu do wskazywanych przez nie rzeczy, i powiniene
zapewne z nich skorzysta, chyba e jeste w pakiecie klasy
definiujcej metody tego obiektu i pracujesz nad nimi. Inaczej
mowic, bd tak dobry i nie naruszaj hermetyzacji bez istotnego
powodu. Perl nie wymusza hermetyzacji. Nie jestemy tu
totalitarystami. Oczekujemy jednak zachowania podstawowych zasad
uprzejmoci.
Mona posluy si operatorem ref() do stwierdzenia, na jaki typ rzeczy
wskazuje odwolanie. Zobacz podrcznik perlfunc(1).
Operator bless() moe by uywany do powizania obiektu, na ktory wskazuje
odwolanie, z pakietem funkcjonujcym jako klasa obiektowa. Zobacz
podrcznik perlobj(1).
Typeglob moe by dereferencjowane w ten sam sposob jak odwolanie, gdy
skladnia dereferencji zawsze wskazuje na podany rodzaj odwolania.
Zatem ${*foo} i ${\$foo} wskazuj na t sam zmienn skalarn.
A oto sztuczka do interpolacji wywolania procedury w lacuchu:
print "Procedura mysub tym razem zwrocila @{[mysub(1,2,3)]} .\n";
Dziala to w tak, e gdy @{...} znalezione zostanie wewntrz lacucha w
cudzyslowach to zostanie potraktowane jako blok. Blok ten tworzy
odwolanie do jednoelementowej anonimowej tablicy zawierajcej wynik
wywolania mysub(1,2,3) [odwolanie to utworzone bdzie dziki nawiasom
kwadratowym]. Zatem caly blok zwraca odwolanie do tablicy, ktora
nastpnie podlega dereferencji powodowanej przez @{...}. Jej warto, jako
umieszczona w lacuchu w cudzyslowach podlega interpolacji w napis.
Takie szykany przydaj si take w dowolnych wyraeniach:
print "That yields @{[$n + 5]} widgets\n";
Odwo/l/lania symboliczne
Powiedzielimy, e niezdefiniowane cele odwolania w razie potrzeby
zaistniej [podczas dereferencji]. Nie mowilimy jednak, co si dzieje,
gdy warto uyta jako odwolanie jest ju zdefiniowana, ale NIE JEST
odwolaniem stalym. Jeeli uyjesz odwolania w takim przypadku, to bdzie
ono potraktowane jak odwolanie symboliczne. To znaczy, wartoci skalara
zostanie NAZWA zmiennej a nie bezporednie dowizanie do (by moe
anonimowej) wartoci.
Niektorzy czsto spodziewaj si, e dziala to jako tak. I rzeczywicie.
$name = "foo";
$$name = 1; # ustawia $foo
${$name} = 2; # ustawia $foo
${$name x 2} = 3; # ustawia $foofoo
$name->[0] = 4; # ustawia $foo[0]
@$name = (); # czyci @foo
&$name(); # wywoluje &foo() (jak w Perl 4)
$pack = "THAT";
${"${pack}::$name"} = 5; # ustawia $THAT::foo bez rozwinicia(eval)
Jest to bardzo silne narzdzie, ale nieco niebezpieczne, gdy moliwe
jest, ze szczerym zamiarem uycia odwolania stalego, przypadkowe uycie
symbolicznego. Moesz si przed tym uchroni piszc:
use strict 'refs';
a dla reszty otaczajcego bloku bd dozwolone tylko odwolania stale.
Wewntrzny blok moe si temu sprzeciwi przy pomocy
no strict 'refs';
Dla odwola symbolicznych widoczne s tylko zmienne pakietu (globalne,
nawet jeli lokalnie). Zmienne leksykalne (deklarowane przy pomocy my())
nie zawieraj si w tablicy symboli, zatem s niewidoczne dla tego
mechanizmu. Na przyklad:
local $wartosc = 10;
$ref = "wartosc";
{
my $wartosc = 20;
print $$ref;
}
Nadal bdzie drukowa 10, a nie 20. Pamitaj, e local() dziala na zmienne
pakietu, ktore dla samego pakietu wszystkie s "globalne".
Odwo/l/lania niezbyt symboliczne
Now cech poprawiajc czytelno, wprowadzon w perlu wersji 5.001, jest to,
e nawiasy wokol odwolania symbolicznego zachowuj si jak znaki
cudzyslowu, czyli tak, jakby zawsze zawieraly wewntrz lacuch. To
znaczy, e
$push = "pop on ";
print "${push}over";
mialo zawsze znaczenie wydrukowania "pop on over", bez wzgldu na fakt,
e "push" jest slowem zarezerwowanym. Zostalo to uogolnione tak, by
dziala rownie poza cudzyslowami, zatem
print ${push} . "over";
a nawet
print ${ push } . "over";
maj ten sam rezultat. (Spowodowaloby to bld skladni w Perlu 5.000, cho
Perl 4 dopuszcza co takiego w postaci bez odstpow.) Zauwa, e
konstrukcja ta nie nie jest uwaana za odwolanie symboliczne gdy uywasz
strict refs:
use strict 'refs';
${ bareword }; # dobrze, znaczy $bareword.
${ "bareword" }; # bld, odwolanie symboliczne.
Podobnie, z powodu wszelkiego indeksowania przy pomocy pojedynczych
slow, zastosowalimy t sam regul do kadego z golych slow uytego do
indeksowania hasza. Zatem teraz, zamiast
$array{ "aaa" }{ "bbb" }{ "ccc" }
moesz napisa po prostu
$array{ aaa }{ bbb }{ ccc }
i nie martwi si o to, czy indeksy s slowami zarezerwowanymi. W tych
rzadkich przypadkach, gdy chcesz zrobi co w rodzaju
$array{ shift }
moesz wymusi interpretacj slowa jako zarezerwowanego dodajc cokolwiek,
co zrobi ze wicej ni gole slowo:
$array{ shift() }
$array{ +shift }
$array{ shift @_ }
Przelcznik -w bdzie Ci ostrzegal, jeli zinterpretuje slowo
zarezerwowane jako lacuch. Nie bdzie jednak ostrzegal o uyciu slow
pisanych malymi literami, gdy lacuch jest faktycznie cytowany.
Pseudo-hasze: Uywanie tablicy jak hasza
OSTRZEENIE: Niniejsza sekcja opisuje cech eksperymentaln. W
przyszlych wersjach szczegoly mog ulec zmianie bez powiadomienia.
Poczwszy od Perla 5.005 moesz w pewnych kontekstach poslugiwa si
odwolaniem do tablicy, mimo e normalnie wymagaj one odwolania do hasza.
Pozwala to na dostp do elementow tablicy przy uyciu nazw symbolicznych,
tak jakby byly one polami struktury.
eby to zadzialalo tablica musi zawiera dodatkow informacj. Pierwszym
elementem tablicy powinno by odwolanie do hasza odwzorowujcego nazwy
pol na indeksy tablicy. Oto przyklad:
$struct = [{foo => 1, bar => 2}, "FOO", "BAR"];
$struct->{foo}; # to samo, co $struct->[1], tj. "FOO"
$struct->{bar}; # to samo, co $struct->[2], tj. "BAR"
keys %$struct; # zwroci ("foo", "bar") w jakiej kolejnoci
values %$struct; # zwroci ("FOO", "BAR") w jakiej kolejnoci
while (my($k,$v) = each %$struct) {
print "$k => $v\n";
}
Jeli sprobujesz usun klucze z takiego pseudo-hasza lub bdziesz probowal
sign do nieistniejcych pol, perl zglosi wyjtek. W celu poprawy
wydajnoci, Perl moe te wykona na etapie kompilacji tlumaczenie nazw pol
na odpowiadajce im indeksy tablicy dla opisanych odwola. Patrz
podrcznik fields(3).
Szablony funkcji
Jak wyjaniono powyej, zamknicie jest anonimow funkcj z dostpem do
zmiennych leksykalnych widocznych podczas jej kompilacji. Zachowuje
ona dostp do tych zmiennych nawet wtedy, gdy jest wykonywana poniej,
tak jak funkcja obslugi sygnalu (signal handler) czy wywolanie wsteczne
Tk.
Poslugiwanie si zamkniciem jako szablonem funkcji umoliwia tworzenie
wielu podobnie dzialajcych funkcji. Zalomy, e potrzebujesz funkcji o
nazwach pochodzcych od ronych kolorow zmieniajcych czcionk HTML.
print "Hej, ", red("uwaaj"), "na to ", green("wiatlo");
Funkcje red() i green() bd bardzo podobne. By je stworzy, przypiszemy
zamknicie do typeglob nazwy funkcji, ktor probujemy skonstruowa.
@kolory = qw(red blue green yellow orange purple violet);
for my $nazwa (@kolory) {
no strict 'refs'; # pozwol na operowanie tablic symboli
*$nazwa = *{uc $nazwa} = sub { "<FONT COLOR='$nazwa'>@_</FONT>" };
}
Teraz wszystkie te funkcje bd istnie niezalenie od siebie. Moesz
wywolywa red(), RED(), blue(), BLUE(), green(), etc. Technika ta
zarowno skraca czas kompilacji jak i zmniejsza zuycie pamici, jest te
mniej naraona na bldy, gdy kontrola skladni odbywa si podczas
kompilacji. Istotne jest, by wszelkie zmienne w anonimowej procedurze
byly zmiennymi leksykalnymi by stworzy poprawne zamknicie. Z tego
powodu uyto my dla zmiennej sterujcej ptli.
Jest to jedno z jedynych miejsc, gdzie dostarczenie prototypu do
zamknicia ma sens. Jeli chcialby narzuci kontekst skalarny dla
argumentow powyszych, przykladowych funkcji (pewnie nie najlepszy
pomysl w tym przypadku), moesz zapisa to inaczej:
*$nazwa = sub ($) { "<FONT COLOR='$nazwa'>$_[0]</FONT>" };
Jednake, poniewa sprawdzanie protypow odbywa si podczas kompilacji,
powysze przypisanie zostanie wykonane za pono, by bylo przydatne.
Moglby to obej przez wloenie calej ptli przypisa do wntrza bloku
BEGINu, wymuszajc wykonanie go w czasie kompilacji.
Dostp do zmiennych leksykalnych zmieniajcych typ -- jak te w ptli for
powyszego przykladu-- dziala wylcznie z zamkniciami, a nie z
procedurami w ogole. Zatem w przypadku ogolnym, procedury nazwane nie
zagniedaj si prawidlowo, cho robi to procedury anonimowe. Jeli nawykle
do uywania zagniedonych procedur z wlasnymi prywatnymi zmiennymi w
innych jzykach programowania, to w Perlu bdziesz musial nad troch
popracowa. Intuicyjna metoda kodowania tego typu rzeczy spowoduje
tajemnicze ostrzeenia ``will not stay shared'' (nie pozostanie
wspolne). To, na przyklad, nie zadziala:
sub zewn {
my $x = $_[0] + 35;
sub wewn { return $x * 19 } # LE
return $x + wewn();
}
Obejcie jest nastpujce:
sub zewn {
my $x = $_[0] + 35;
local *wewn = sub { return $x * 19 };
return $x + wewn();
}
Teraz wewn() moe by wywolana tylko z wntrza zewn(), z powodu
tymczasowego przypisania zamknicia (procedury anonimowej). Ale kiedy
jest wywolywana, to ma zwykly dostp do zmiennej leksykalnej $x z
zakresu procedury zewn().
Ma to interesujcy skutek tworzenia funkcji lokalnych wzgldem innych
funkcji, co normalnie nie jest obslugiwane w Perlu.
OSTRZEENIE
Nie moesz (w uyteczny sposob) posluy si odwolaniem jako kluczem hasza.
Zostanie ono zamienione na lacuch:
$x{ \$a } = $a;
Jeli sprobujesz zdereferencjonowa klucz, nie otrzymasz odwolania
stalego a lacuch i nie uzyskasz tego, co probowale. W zamian mona
napisa co podobnego do:
$r = \@a;
$x{ $r } = $r;
a nastpnie uy values(), co zwroci rzeczywiste odwolania, zamiast uycia
keys(), gdy klucze odwolaniami nie bd.
Standardowy modul Tie::RefHash umoliwia wygodny sposob obejcia tego
problemu.
ZOBACZ TAKE
Poza oczywist dokumentacj, pouczajca moe by analiza kodu rodlowego.
Kilka raczej patologicznych przykladow uycia odwola znajdziesz w tecie
regresji t/op/ref.t w katalogu rodel Perla.
Zobacz rownie podrczniki perldsc(1) i perllol(1), opisujce poslugiwanie
si odwolaniami do tworzenia zloonych struktur danych, oraz perltoot(1),
perlobj(1) i perlbot(1) opisujce ich uycie do tworzenia obiektow.
INFORMACJE O T/L/LUMACZENIU
Powysze tlumaczenie pochodzi z nieistniejcego ju Projektu Tlumaczenia
Manuali i moe nie by aktualne. W razie zauwaenia ronic midzy powyszym
opisem a rzeczywistym zachowaniem opisywanego programu lub funkcji,
prosimy o zapoznanie si z oryginaln (angielsk) wersj strony podrcznika.