Paprogramės, funkcijos, parametrų perdavimas |
PERL'e sąvokos paprogramė ir funkcija - sinonimai, todėl galima vartoti tiek vieną tiek ir kitą terminą. Paprogramės paskirtis yra tokia pat kaip ir funkcijos C/C++ tai yra: suskaldyti didelę programą į mažesnes dalis tam, kad ji būtų lengviau suprantama bei sudarytų galimybę ateityje panaudoti tą pačią paprogramę panašioms procedūroms atlikti.
Paprogramė gali būti apibrėžta bet kurioje pagrindinės programos vietoje. Paprogramei apibrėžti naudojama sintaksė:
subvardas
- paprogramės sukūrimas be apibrėžimo subvardas
(prototipas) - paprogramės sukūrimas, nurodant parametrų sąrašą, bet be apibrėžimo subvardas
{blokas} - paprogramės apibrėžimas su operatorių bloku subvardas
(prototipas) {blokas} - paprogramės apibrėžimas su parametrų sarašu ir operatorių bloku.
Pavyzdys:
sub say_hello {
print "hello, world!\n";
}
Paprogramėje
apibrėžti ir naudojami kintamieji yra grobalūs, jei jie neapibrėžiami funkcijų
my()
arba
local() pagalba. Paprogramės tekstas gali būti saugomas kitame faile
nei pati programa. Tuomet paprogramė prijungiama naudojant operatorius
do,
require, use. Funkcijos
eval() argumentas gali būti paprogramė,
todėl tai dar vienas būdas perduoti paprogramę pagrindinei programai.
Konstrukcija do filename siejama su specialiais kintamaisiais
$! ir
$@. Pirmasis naudojamas pranešimams apie
sistemines klaidas saugoti, antrasis kintamasis saugo pranešimus apie
paprogramės kompiliavimo arba vykdymo klaidas. Pavyzdžiui:
# Failas "1.pl"
# !/usr/bin/perl
do "2.pl";
print " Klaida: $@\n" if $@;
print " Sistemnine klaidas: $!\n" if $!;
# Failas "2.pl"
# !/usr/bin/perl
$x = <>;
$y = <>;
print "Dalyba = ", $x/$y, "\n";
Paprogramės iškvietimas
Paprastai paprogramė atpažįstama pagal prefiksą &, todėl iškviečiant paprogramę galima naudoti tokia sintaksę:
&vardas args;
&vardas (args);
&vardas;
Jei iškviečiant paprogramę, po jos vardo naudojami skliaustai ( ) arba prieš tai paprogramė buvo apibrėžta ar importuota, tuomet galime praleisti prefiksą "&". Jeigu paprogramė iškviečiama per nuorodą, tuomet prefiksas "&" būtinas, pavyzdžiui.
$sub_ref = sub { ..... };
...
&sub_ref (args);
...
&sub_ref;
Paprogramė gali būti naudojama kaip funkcija, grąžinanti reikšmę. Pagal nutylėjimą gražinama reikšmė, gauta iš paskutinio paprogramės skaičiavimo arba tai, kas nurodoma funkcijos return() argumente. Argumentų sąrašas, perduodamas paprogramės išvietimo metu yra saugoma specialiame masyve @_ , kuris yra lokalus ir pasiekiamas tik iš konkrečios paprogramės. Pavyzdys:
sub sudetis {
$sum = 0;
foreach $_ (@_) {
$sum += $_; #
sudedami visi elementai
}
return $sum;
}
$a = add(4,5,6); # sudeda 4+5+6 = 15
ir priskiria $a
print add(1,2,3,4,5); # atspausdina 15
print add(1..5); # taip pat 15
Lokalūs kintamieji paprogramėse
PERL kalboje kintamieji pagal nutylėjimą laikomi globaliais t.y. jų galiojimo sritis apribojama paketu. Paketui paprastai priklauso visa programa. Kiekvienas paketas turi savo vardų sritį (angl. namespace). Norint apriboti kintamųjų veikimo sritį bloko arba paprogramės rėmuose, naudojami lokalūs kintamieji. Jie papibrėžiami funkcijomis my() ir local().
Funkcija
my()
Ši funkcija apibrėžia lokalų kintamąjį. Sintaksė:
my (Expr_list);
my Expr;
Pavyzdys:
sub add {
my ($sum)= 0; # $sum lokalus kintamasis
foreach $_ (@_) {
$sum += $_; # sumuojam visus elementus
}
return $sum;
}
Lokalūs kintamieji, apibrėžti funkcija my(), veikimo sritis:
paprogramė
blokas, apskliaustas {}
išraiška, perduoda funkcija eval()
failas, priklausomai nuo to, kokioje vietoje buvo panaudota funkcija my().
Funkcija
local()
Ši funkcija apibrėžia kintamąjį, bet ne lokalų, o laikinas reikšmes globaliems kintamiesiems:
paprogramėse
blokuose, apskliaustuose {}
išraiškose, perduotose funkcija eval()
failuose.
Sintaksės variantai:
local Expr;
local ($myvar,
@myarray, %myhash);
local $pi = 3.1415;
local ($pi, @array) = (3.1514, 1, 2);
Svarbu suprasti
skirtumus tarp funkcijų my() ir
local(). Tai padės pavydžiai:
$value = "Originalus"; output(); keisti(); output(); sub keisti { local ($value) = "Laikinas"; # Naudojam funkciją local output(); } sub output { print "$value\n"; }
Rezultatai bus tokie:
Originalus
Laikinas
Originalus
Jei pakeisime paprogramėje keisti() funkciją local į my(), tuomet rezultatai bus tokie:
Originalus
Originalus
Originalus
Parametrų perdavimas paprogramėms
Informacija paprogramei ir atgal perduodama per parametrus (argumentus). Parametrų perdavimas paprogramei atliekamas per specialų kintamąjį @_ , kuris yra lokalus duotai paprogramei. Visi parametrai saugomi masyvo elementuose $_[0], $_[1] ... Toks mechanizmas leidžia perduoti neapibrėžtą parametrų skaičių. Parametrų perdavimas per kintamąjį @_ prilygsta C/C++ naudojamai nuorodos paskirčiai funkcijos parametrų sąraše.
Jei paprogramės parametras yra masyvas, jo elementai taip pat prisikiriami masyvo @_ elementams. Tačiau, jei norima perduoti ne vieną, o kelis masyvus, tuomet naudojami typeglob tipo kintamieji arba nuorodos. typeglob tipo kintamieji turi prefiksą "*", kuris reiškia, kad dirbama su kintamųjų vardų sritimi ir kintamasis sutokiu pavadinimu gali būti bet kokio tipo t. y. skaliarinis, masyvas, asociatyvinis masyvas ar funkcija. Kitaip sakant, "*" reiškia nuorodą į simbolių lentelę. Naudojant paprogramės parametrų sąraše typeglob kintamuosius, imituojamas duomenų perdavimas per nuorodas, pavyzdžiui:
# Duomenų perdavimas paprogramėms per typeglob kintamuosius
sub double_arg {
local (*mylist, *myhash)
= @_;
# būtina
naudoti local()
foreach $item (@mylist) {
$item *=2;
}
foreach $key (keys %myhash) {
$myhash{$key} *=2;
}
}
@somelist = (1,2,3);
%somehash = ("one"=>5, "two"=>6, "three"=>7);
print "Pradines reiksmes:\n\@somelist =
@somelist\n";
foreach $key (keys %somehash) {
print "\$somehash{$key} = $somehash{$key}";
}
double_arg(*somelist, *somehash);
print "Pakeistos reiksmes:\n\@somelist =
@somelist\n";
foreach $key (keys %somehash) {
print "\$somehash{$key} = $somehash{$key}";
}
Kitas būdas keletos masyvus perdavimui paprogramei - tai nuorodų panaudojimas. Nuorodos PERL'e yra skaliariniai kintamieji, todėl jie perduodami, per specialų kintamąjį @_ kaip ir bet kuris kitas skaliaras. Ankstesnis pavyzdys, panaudojus nuorodas, atrodytų taip:
# Duomenų perdavimas paprogramėms per
nuorodas
sub double_arg {
my($listref,
$hashref)
= @_;
# būtina naudoti
my()
foreach $item (@$listref) {
$item *=2;
}
foreach $key (keys %$hashref) {
$$hashref{$key} *=2;
}
}
@somelist = (1,2,3);
%somehash = ("one"=>5, "two"=>6, "three"=>7);
print "Pradines reiksmes:\n\@somelist =
@somelist\n";
foreach $key (keys %somehash) {
print "\$somehash{$key} = $somehash{$key}";
}
double_arg(\@somelist, \%somehash);
print "Pakeistos reiksmes:\n\@somelist =
@somelist\n";
foreach $key (keys %somehash) {
print "\$somehash{$key} = $somehash{$key}";
}
Nuorodos taip pat naudojamos ir tuo atveju, kai norima
iš paprogramės grąžinti daugiau nei vieną masyvą,
pavydžiui:
($array_ref, $hash_ref) = somefunc();
sub somefunc {
my @array;
my %hash;
# ...
return ( \@array, \%hash );
}
Prototipai
Visos PERL built-in funkcijos turi apibrėžtą sintaksę, t.y. vardą, parametrų skaičių ir jų tipą. Norint apibrėžti, kokio tipo parametrai turi būti įvedami iškviečiant funkciją, naudojami prototipai. Prototipas - tai įrašas funkcijos parametrų sąrašę, kuris tam tikrais simboliais apibrėžia, kiek ir kokie parametrai turi būti įvedami. Prototipe naudojami sekantys simboliai:
Simbolis | Duomenų tipas |
$ | Skaliarinis |
@ | Masyvas |
% | Asociatyvinis masyvas |
& | Anoniminė paprogramė |
* | typeglob |
; | Skiria būtinus parametrus nuo nebūtinų |
\ | Pasako, kad parametro vardas, turi prasidėti simbolių, einančiu po \ |
Prototipų pavyzdžiai
Apibrėžtas prototipas | Funkcijos iškvietimas |
---|---|
sub mylink ($$) |
mylink $old, $new |
sub myvec ($$$) |
myvec $var, $offset, 1 |
sub myindex ($$;$) |
myindex &getstring, "substr" |
sub mysyswrite ($$$;$) |
mysyswrite $buf, 0, length($buf) -
$off, $off |
sub myreverse (@) |
myreverse $a,$b,$c |
sub myjoin ($@) |
myjoin ":",$a,$b,$c |
sub mypop (\@) |
mypop @array |
sub mysplice (\@$$@) |
mysplice @array,@array,0,@pushme |
sub mykeys (\%) |
mykeys %{$hashref} |
sub myopen (*;$) |
myopen HANDLE, $name |
sub mypipe (**) |
mypipe READHANDLE, WRITEHANDLE |
sub mygrep (&@) |
mygrep { /foo/ } $a,$b,$c |
sub myrand ($) |
myrand 42 |
sub mytime () |
mytime |
Rekursinės paprogramės
PERL programose galima naudoti rekursines paprogrames. Rekursinių paprogramių kintamieji turi būti lokalūs t.y. apibrėžti funkcijomis my() arba local(). Todėl kiekvieną kartą, kai paprogramė iškviečia pati save, sukuriama nauja kintamųjų kopija. Panagrinėkime pavyzdį, kuris parodo katalogo ir jame esančių subkatalogų failų sąrašus.
sub tree {
local (*ROOT);
my ($root) = $_[0];
opendir ROOT, $root;
my (@filelist) = readdir ROOT;
closedir ROOT;
for $x (@filelist) {
if ($x ne "." and $x ne "..") {
$x = $root."/".$x;
print " $x\n" if (-f $x);
if (-d $x) {
print
"$x:\n";
system (sleep
1);
tree($x);
}
}
}
}