Referencje w Perlu
Narzedzia informatyczne w j֒ ezykoznawstwie֒
Marcin Junczys-Dowmunt 21 lutego 2008
1 Wprowadzenie do referencji
Referencje to tak naprawde nazwy zmiennych. Mo˙zemy traktowa´c zmienne jako przedmioty֒ rzeczywiste, a referencje jako ich oznaczenia. Tak jak w ´swiecie rzeczywistym, istnieje tylko jeden konkretny obiekt, niemniej mo˙ze on mie´c wiele nazw. Referencje to trzeci typ danych skalarnych (a nie z lo˙zonych) w Perlu obok zmiennych liczbowych i la´ncuch´ow znakowych.
1.1 Referencje do podstawowych typ´ow zmiennych
Referencje do dowolnych zmiennych tworzymy za pomoca \. Poniewa˙z referencje to dane֒ skalarne, przechowujemy je w zmiennych skalarnych, tak jak liczby lub la´ncuchy znakowe.
1 use s t r i c t;
my @ a r r a y = (1 , 2 , 3);
my % hash = ( jeden = > 1 , dwa = > 2 , trzy = > 3);
5 my $ s c a l a r = " Taki sobie s k a l a r"; my $aref = \ @ a r r a y;
my $href = \% hash ; my $sref = \ $ s c a l a r;
1.2 Anonimowe listy i hasze
Powy˙zej zdefiniowali´smy konkretne zmienne skalarne, tablicowe i haszowe, a nastepnie stwo-֒ rzyli´smy referencje do nich. W przypadku tablic i hasz´ow mo˙zna sie obej´sc bez tego kroku֒ po´sredniego, tworzac anonimowe tablice i hasze.֒
1 use s t r i c t;
my $aref = [ 1 , 2 , 3 ];
my $href = { jeden = > 1 , dwa = > 2 , trzy = > 3 };
Operator [...] tworzy liste (mo˙ze by´c pusta) i zwraca automatycznie referencj֒ e do tej֒ tablicy. Podobnie {...} tworzy hasz (tak˙ze mo˙ze by´c pusty) i zwraca odpowiednia referencj֒ e.֒ Wewnatrz tych operator´֒ ow zachodza odpowiednio konteksty listowe i haszowe.֒
1
1.3 Sposoby dost epu֒
1 use s t r i c t;
my @ a r r a y = (1 , 2 , 3);
my % hash = ( jeden = > 1 , dwa = > 2 , trzy = > 3);
5 my $ s c a l a r = " Taki sobie s k a l a r"; my $aref = \ @ a r r a y;
my $href = \% hash ; my $sref = \ $ s c a l a r;
10
print " T a b l i c a r e f e r o w a n a przez \ $aref ma "; print s c a l a r @ { $aref } . " e l e m e n t o w\ n \ n "; print " Hash r e f e r o w a n y przez \ $href ma ";
15 print s c a l a r keys %{ $href } . " k l u c z y\ n \ n ";
print " K a n o n i c z n y s p o s o b d o s t e p u: \ n ";
print " $ { $aref }[0] == $ a r r a y [0]\ n ";
print " $ { $href }{ jeden } == $hash { jeden }\ n ";
20 print " $ { $ref } == $ s c a l a r"
print " S k r o c o n y s p o s o b dostepu , gdy nie ma w i e l o z n a c z n o s c i : \ n ";
print " $ $ a r e f [0] == $ a r r a y [0]\ n ";
print " $ $ h r e f{ jeden } == $hash { jeden }\ n ";
25 print " $$ref == $ s c a l a r"
print " N o t a c j a ’ s t r z a l k o w a ’: \ n ";
print " $aref - >[0] == $ a r r a y [0]\ n ";
print " $href - >{ jeden } == $hash { jeden }\ n ";
2
1.4 Wygodne wy´swietlanie
Funkcja Data::Dumper pozwala na wygodne i przejrzyste wy´swietlanie z lo˙zonych struktur danych. Radzi sobie nawet z cyklicznymi strukturami.
1 use s t r i c t;
use Data :: D u m p e r;
my $test = {
5 l i c z b o w o = > [1 , 2 , 3] ,
s l o w n i e = > [’ jeden ’, ’ dwa ’, ’ trzy ’] , cykl = > $test ,
};
10 print D u m p e r( $test );
1.5 Uwaga!
1 use s t r i c t;
use Data :: D u m p e r;
my @ a r r a y = (1 , 2 , 3);
5
my $ a r e f 1 = \ @ a r r a y; # r e f e r e n c j a do @ a r r a y
my $ a r e f 2 = [ @ a r r a y ] # r e f e r e n c j a do k o p i i @ a r r a y
$aref1 - >[0] = 4;
10 $aref2 - >[1] = 5;
print D u m p e r (\ @ a r r a y );
3
2 Tablica tablic
W perlu nie ma prawdziwych tablic wielowymiarowych. Mo˙zna uzyska´c ten sam efekt budujac֒ tablice tablic, kt´ore nie r´o´znia si֒ e pod wzgl֒ edem funkcji i wydajno´sci od prawdziwych tablic֒ wielowymiarowych. W zale˙zno´sci od liczby zagnie˙zd˙ze´n mo˙zna w ten spos´ob otrzymac tablice֒ n-wymiarowe.
2.1 Przyk lad: Indeksowany tekst
1 my @ t e k s t;
while( < >) { chomp;
push( @tekst , [ split(/[\s. ,;:\ -?!)(]+/ , $_ ) ]);
5 }
print " W y r a z e m na p o z y c j i (3 ,5) jest : " . w y r a z _ n _ m (3 ,5 ,\ @ t e k s t) . " \ n "; print " W y r a z e m na p o z y c j i (10 ,2) jest : " . w y r a z _ n _ m (10 ,2 ,\ @ t e k s t) . " \ n ";
10 sub w y r a z _ n _ m {
my ( $n , $m , $ t e k s t) = @_ ;
if( $n -1 < @ $ t e k s t and $m -1 < @ { $tekst - >[ $n -1]}) { r e t u r n $tekst - >[$n -1] - >[$m -1];
}
15 r e t u r n " Nie ma t a k i e g o w y r a z u";
}
4
3 Tablica hasz´ ow
Np. reprezentacja graf´ow za pomoca takiej struktury jest bardzo wygodna i oszcz֒ edna. Np.֒ gdy wierzcho lki maja reprezentacj֒ e liczbow֒ a, mo˙zna je traktowa´c jak indeksy tablicy. Gdy֒ taki graf ma ma lo krawedzi nie op laca si֒ e kodowa´c wierzcho lk´ow po l֒ aczonych za pomoc֒ a֒ tablicy, poniewa˙z tablica ma tyle element´ow ile wyno´sci jej najwiekszy indeks (plus jeden).֒ Hasz bedzie mia l tylko tyle element´֒ ow ile bedzie kraw֒ edzi wychodz֒ acych.֒
Nie moge akurat wymy´sle´c prostego przyk ladu. Korzysta lem ju˙z nie raz z takiej re-֒ prezentacji, ale by ly to z lo˙zone problemy (np. zliczanie kookurencji wyraz´ow w korpusach r´ownoleg lych).
5
4 Hasz tablic
Hasz tablic jest idealna struktur֒ a danych, gdy jednemu kluczowi odpowiada wiele warto´sci.֒ Mo˙zemy je wtedy umie´sci´c w tablicy, a referencje do tablicy jako warto´s´c w haszu.֒
4.1 Przyk lad: Lemmatyzator
1 use s t r i c t;
my $ l e x i c o n = {
a n a l i t y k = > [ ’ a n a l i t y k a _ R ’, ’ a n a l i t y k _ R ’ ] ,
5 a n a l i t y k a = > [ ’ a n a l i t y k a _ R ’, ’ a n a l i t y k _ R ’ ] , a n a l i t y k a c h = > [ ’ a n a l i t y k a _ R ’, ’ a n a l i t y k _ R ’ ] , a n a l i t y k a m i = > [ ’ a n a l i t y k a _ R ’, ’ a n a l i t y k _ R ’ ] , a n a l i t y k i = > [ ’ a n a l i t y k a _ R ’ ] ,
a n a l i t y k i e m = > [ ’ a n a l i t y k _ R ’ ] ,
10 a n a l i t y k o = > [ ’ a n a l i t y k a _ R ’ ] ,
a n a l i t y k o m = > [ ’ a n a l i t y k a _ R ’, ’ a n a l i t y k _ R ’ ] , a n a l i t y k o w i = > [ ’ a n a l i t y k _ R ’ ] ,
a n a l i t y k u = > [ ’ a n a l i t y k _ R ’ ] , a n a l i t y k\ ow = > [ ’ a n a l i t y k _ R ’ ] ,
15 a n a l i t y k\ a = > [ ’ a n a l i t y k a _ R ’ , ’ a n a l i t y k _ R ’ ] , a n a l i t y k\ e = > [ ’ a n a l i t y k a _ R ’ ] ,
# . . . d a l s z e w p i s y }
20 while( < >) { chomp;
print " L e m a t y z u j e z d a n i e: $_ \ n ";
my @ t o k e n s = split(/[\s. ,;:\ -?!)(]+/ , $_ );
25 f o r e a c h my $ t o k e n ( @ t o k e n s) {
print " $ t o k e n : " . join(" | ", @ { $lexicon - >{lc( $ t o k e n )}}) ." \ n "; }
}
Wyrazy tekstowe nie zawsze mo˙zna jednoznacznie przyporzadkowa´c do jednego lematu.֒ Gdy uwzglednimy synktretyzm i inne informacje jak np. przypadek, liczba itp., to mamy֒ jeszcze wiecej wieloznaczno´sci, czyli d lu˙zsze listy.֒
6
5 Hasz hasz´ ow
Hasze zawierajace hasze to kolejna bardzo przydatna struktura danych. Jest ona wolniejsza֒ od struktury wykorzystujaca tablice, ale zawiera tylko dokladnie tyle element´֒ ow ile trzeba.
5.1 Przyk lad: Wyszukiwanie bigram´ow czerwony krzyz
czerwony baron klucz zapadkowy klucz udarowy klucz dekodujacy program dekodujacy program rozwoju ...
Tablica 1: Przyk ladowe kolokacje bigramowe
1 use s t r i c t;
my % b i g r a m y = ( c z e r w o n y = > {
5 krzyz = > 1 , baron = > 1 , } ,
klucz = > {
z a p a d k o w y = > 1 ,
10 u d a r o w y = > 1 , d e k o d u j a c y = > 1 , } ,
p r o g r a m = > {
d e k o d u j a c y = > 1 ,
15 r o z w o j u = > 1 , } ,
);
while( < >) {
20 my @ t o k e n s = split(/[\s. ,;:\ -?!)(]+/ , $_ );
for(my $i = 0; $i +1 < @ t o k e n s; $i ++) {
if( $ b i g r a m y{ $ t o k e n s[ $i ]} - >{ $ t o k e n s[ $j ]}) {
print " Z n a l e z i o n o b i g r a m : $ t o k e n s[ $i ] $ t o k e n s[ $i +1] ";
}
25 }
}
Przyk lad mo˙zna oczwi´scie rozszerzy´c do kolokacji o dowolnej liczbie wyraz´ow. Wtedy trzeba jednak stosowa´c np. rekurencje w celu przegl֒ adania struktury danych. Jest to przy֒ okazji przyk lad na prosty automat sko´nczony lub proste drzewo o dowolnej liczbie rozga lezie´֒ n.
7
6 Inne struktury danych
Za pomoca referencji do tablic i hasz´֒ ow mo˙zna tworzy´c struktury danych o dowolnej liczbie zagnie˙zd˙ze´n. Jedynie rozmiar dostepniej pami֒ eci nas ogranicza. Mo˙zemy zbudowa´c drzewa,֒ automaty sko´nczone lub inne rodzaje graf´ow, traktowa´c hasze jako rekordy, tablice jako n-tki itp. Nale˙zy te˙z pamieta´c, ˙ze jedn֒ a referencj֒ e mo˙zna wykorzysta´c wi֒ ecej ni˙z raz, tworz֒ ac w֒ ten spos´ob strukture, nie powielaj֒ ac dane.֒
1 my $ r o d z i c e = [ qw( Antek Berta ) ];
my $ b r a c i a = { Juzek = > {
r o d z i c e = > $rodzice ,
5 wiek = > 20 , } ,
Benek = > {
r o d z i c e = > $rodzcie , wiek = > 25 ,
10 } ,
};
print D u m p e r( $ b r a c i a );
Takie struktury przydaja si֒ e przy tworzeniu automat´֒ ow sko´nczonych, za pomoca kt´orych֒ mo˙zna wydajnie zapamieta´c i wyszukiwa´c np. dowolne kolokacje o dowolnej d lugo´sci.֒
8