Perl Mi a Perl Frozen Bubble Perl történetér l
Document Sample


Perl Mi a Perl?
általános célú programozási nyelv
¡
Web fejlesztés
¡
Rendszeradminisztráció
¡
GUI programozás
¡
Hálózati programozás
¡
...
Gyakorlatias nyelv:
¡
Hatékony, jól használható, teljes
¡
A szépség nem volt cél (minimalitás, elegancia)
Használhatjuk struktúrált és objektum-orientált
programozáshoz is
Practical Extraction and Report Language Rengeteg kiegészít modul
¢
Pathologically Eclectic Rubbish Lister
1 2
Frozen Bubble Perl történetér l
£
http://www.frozen-bubble.org
Larry Wall alkotta a nyelvet saját céljaira az awk és
a sed korlátai miatt
A világ hackereinek megtetszett...
Perl 1: a Perl és a világ találkozása
¡
1987 december 17.
¡
\(...\|...\) helyett (...|...)
Perl 2: új reguláris kifejezések Henry Spencer regex
csomagja révén
Perl 3: bináris adatok kezelése
Perl 4: egy kisebb lépés
A játék Perl-ben készült
SDL-t használ a grafika megjelenítéséhez
3 4
Perl5 A Perl jöv je
£
Perl 5: 1994 októberében 5.000 Perl6:
Perl5 nagy lépés Körülbelül 2000 nyarán jelentették be, hogy el
¡
¡
ez tartalmaz mindent, ami a Perlben lényeges és fogják készíteni
jó ¡
A közösség fejleszti
¡
Modulok, tie, OO ¡
Fontos, hogy Perl maradjon
¡
Threads ¡
Fontos, hogy 16 év munkájával kompatibilis
¡
i18n, l10n legyen
¡
POSIX ¡
Parrot: a fordító és az értelmez szeparálása
¢
debugger, interaktív környezet Python kódot is lehessen fordítani Parrot bytekódra
¤
¡
regexp Java bytecode to Parrot bytecode konverter
¤
¡
hasonló: Common Language Runtime
¤
¡
Lexikális hatókör (lexical scope)
¡
Beágyazható és kiterjeszthet ¢
Legfrissebb: perl 5.8.5
5 6
hello.pl
Hello world!
print “Hello world!\n”
Futtatása:
Perl bevezetés perl -e 'print “Hello world!\n”'
¡
¡
Beleírjuk a hello.pl nev fileba, majd perl
hello.pl
¡
UNIX: chmod +x hello.pl, valamint egy shebang
sor hozzáadása a filehoz:
#!/usr/bin/perl -w
print “Hello world!\n”
¡
Majd egyszer en hello.pl
7 8
Perl bevezetés Perl bevezetés: típusok
Megjegyzések a # jellel tehet k Perl típusai:
¢
A Perl utasításokat ; választja el egymástól Skalárok (scalars)
¡
Nem kell egy sorba írni az utasításokat Sztringek
¤
print 21 + Számok
¤
Referenciák
¤
21,
Listák-tömbök (lists, arrays)
“\n”
¡
Asszociatív tömbök (associative arrays, hashes)
;
¡
Zárójel elhagyható függvényhívásoknál
keys %hash;
keys(%hash);
a nyelv kis és nagybet ket megkülönböztet
9 10
scalars.pl lists.pl
Perl bevezetés: skalárok Perl bevezetés: listák
Szövegek és számok tárolása Tömb és lista szinonímák Perlben
Egy skalár típusú változó nevének els karaktere Mérete dinamikusan változik
¢
mindig $
Nincs méretkorlát
Egy skalár változó tartalmazhat szöveget is, számot
Nem kell el re megadni a lista maximális méretét
¢
is (akár felváltva is) sem
A számokat szövegként is tárolja Lista változók nevének els karaktere mindig @
¢
Listák elemei skalárok lehetnek
Egy lista elemet már skalárként érünk el
11 12
hashes.pl
Perl bevezetés: hash-ek Perl bevezetés: referenciák
Kulcs-érték párok tárolására alkalmasak Szimbolikus referenciák
Hash típusú változók els karaktere mindig % Egy változó nevét tárolhatjuk benne
¢
¡
Az értékek skalárok lehetnek ¡
Nincs jelent s szerepe
¢
Mérete dinamikusan és korlátlanul változik ¡
A strict modul megtiltja a használatukat
Elkérhet a kulcsok illetve az értékek listája
¢
Valódi referenciák (hard references)
A tárolás a gyorsabb elérés érdekében a Perl A továbbiakban 'referenciák'
¡
magánügye ¡
Lényegében mutatók, de null-referencia nincs
¡
Speciális skalár típus
13 14
Perl bevezetés: referenciák Perl bevezetés: referenciák
Mutathat más skalárra, referenciára, listára, hash- Egy változóra a \ operátorral állíthatunk
re, kódra, GLOB-ra és balértékre (például egy referenciát:
substr visszatérési értéke) ¡
\@array, \%hash, \$scalar
Haszna: []: új tömbreferencia konstruálása
¡
Paraméterátadásnál nem kell nagy ¡
[ 2, 3, 5, 7, 11 ]
adatmásolást végezni ¡
Tömb: ( 2, 3, 5, 7, 11 )
Komplex adatszerkezetek {}: új hash-referencia konstruálása
¡
Többdimenziós tömbök { 'I' => 1, 'V' => '5', 'X' => 10, }
¤
¡
Hash/tömb a hash-ben Hash:
¤
¡
Hash-ek tömbje
¤
( 'I' => 1, 'V' => '5', 'X' => 10, )
Stb.
¤
15 16
ref.pl
Perl bevezetés: referencia- Perl bevezetés: referencia-
dereferálás dereferálás
Teljes tömb elérése:
Teljes hash elérése
¡
@$array_ref ¡
%$hash_ref
Tömbreferencia i. Eleme:
Hash-referencia 'key' kulcsú leme:
¡
$array_ref->[i] ¡
$hash_ref->{'key'}
¡
$$array_ref[i] ¡
$$hash_ref{'key'}
¡
Eml: $array[i] ¡
Eml: $hash{'key'}
Egy kifejezés értékének dereferálása, ha a kifejezés
Egy kifejezés értékének dereferálása, ha a kifejezés
eredménye tömbreferencia: eredménye hash-referencia:
¡
@{...} ¡
%{...}
Skalár referencia:
¡
$$scalar_ref
17 18
Always 'use strict;' Perl bevezetés: deklarációk
A strict pragma használatával a fenti problémák Nincs szükség deklarációra
kiküszöbölhet k Alapértelmezetten minden változó globális
¢
Minden változót deklarálni kell local vagy my (pontosabban csomagszint )
kulcsszóval, ellenkez esetben fordítási hibát
¢
Ebb l sok probléma eredhet
¢
kapunk ¡
Deklarálatlan változó használata egy typo miatt
Szimbolikus referenciák nem használhatók Ha egy változó hatóköre túl széles, akkor lehet,
¡
Stb. hogy ugyanazt használjuk több helyen is:
Minden Perl tutorial és könyv tartalmazza az for $i (1..10) {
“always use strict” mondatot, és igazuk is van @array = somefunc($i);
$AoA[$i] = \@array;
}
19 20
Perl bevezetés: deklarációk Mine :)
Egy lehetséges workaround: A my kulcsszóval deklarált változó...
for $i (1..10) { abban a lexikális egységben látható, ahol
¡
@array = somefunc($i); deklarálták
$AoA[$i] = [ @array ]; ¡
Ha a vezérlés elhagyja a deklarálás blokkját,
} akkor a változó azonnal felszabadul
Igazi megoldást a lexikális hatókör változók minden blokkba belépéskor újra létrejön (ez az
¡
nyújtanak elvárt viselkedés!)
Ez az, amit általában lokális (néha automatikus)
változónak nevezünk
21 22
For ciklus lokális változóval Perl bevezetés: elágazások
A ciklus lokális változóval Tetsz leges kifejezés szerepelhet feltételben
¢
for $i (1..10) { Csak a 0, '' (üres sztring), undef hamis
my @array = somefunc($i);
if (feltétel) {
$AoA[$i] = \@array; ...
} }
elsif (feltétel) {
...
}
else {
...
}
23 24
Perl bevezetés: elágazások Perl bevezetés: ciklusok
unless (feltétel) { while (feltétel) {
... ...
} }
Hátracsapott (postconditional) feltételek:
until (feltétel) {
¡
utasítás if feltétel; ...
¡
utasítás unless feltétel; }
print “21 records read.” if $verbose; sleep 1 until $ready;
die “Can't open file: $!\n” print “Hello World!\n” while 1;
unless defined $filehandle;
25 26
Perl bevezetés: ciklusok Perl bevezetés: operátorok
Aritmetikai: +, -, *, /, %, **
C-style (Perl-kód):
Numerikus összehasonlító:
for (my $i=0; $i <= $#array; $i++) {
print “$i: $array[$i]\n”;
¡
==, !=, <, <=, >, >=, <=>
Sztring összehasonlító:
}
Perl-style:
¡
eq, ne, lt, le, gt, ge, cmp
Logikai m veletek
foreach my $element ( @array ) {
print “$element\n”;
¡
&&, ||, !
}
¡
and, or, not, xor
Bitenkénti: &, |, ^, ~
Inkrementálás, dekrementálás: ++, --
Sztring összef zés: .
Értékadás: =
Elágazás: ?:
27
stb. 28
Perl bevezetés: I/O Perl bevezetés: regexpek
File megnyitása: Reguláris kifejezést általában / jelek közé tesszük,
open(HANDLE, “data.txt”) de tehetjük más közé is, csak akkor kell 'az m' (ld.
or die “Can't open data.txt: $!\n”; kés bb)
¢
Olvasás egy file handle-b l:
¢
Mintaillesztés a =~ operátorral illetve a !~
¡
$line = <HANDLE>; operátorral történik
$line nem definiált, ha EOF Használható feltételben is
¡
while ( my $line = <HANDLE> ) { if ( $line =~ /^\w+/ ) {
¡
print $line; ...
} }
close(HANDLE) or die “Can't close: $!”; A '()' karakterekkel körbezárt csoportok a $1, $2, ...
változókban érthet ek el
¢
¡
print “$1” if $line =~ /^(\w+)/;
29 30
example.pl
Perl bevezetés: regexpek
Az illesztés visszaadja egy listában a csoportokat
my ($dir, $filename) =
$absolute_path =~ m#(.*)/([^/]*)#;
Perl b vebben
£
my ($dir, $filename) =
$absolute_path =~ m#(.*)/(.*)#;
Csere is könnyen megy:
my $s = “Peti fizika jegye: 1”;
$s =~ s/\d$/5/;
Minden el fordulás cseréje:
¢
my $s = “Itt a meggy. Kell a meggy?”;
$s =~ s/meggy/dinnye/g;
31 32
perldoc Perl adattípusok
perldoc -f parancs skalár
perldoc perl szám
¡
http://www.perldoc.com ¡
szöveg
nagyon jó dokumentációk referencia
¡
lista vagy tömb
asszociatív tömb, hash (map, dictionary)
¡
asszociatív, mint összekapcsoló, nem mint
zárójelezhet
¢
33 34
check_variable_name.pl
Perl változónevek Változó névterek
els karakter
¢
Minden változótípusnak külön névtere van
$: skalár
@foo, %foo, $foo külön változók
¡
@: lista
$foo[0] -nak nincs köze $foo-hoz!
¡
%: hash
$foo: a foo nev skalár
¡
¡
&: eljárások nevei
@foo: a foo nev tömb
¡
¡
*: type glob
$foo[0]: a foo nev tömb els eleme
¡
¢
¡
második karakter '_' vagy alfa
többi: alnum és '_'
röviden:
¡
/[\$@%&*]?[[:alpha:]_][[:alnum:]_]*/
speciális a filehandle
a Perl bels változóinak nevei nem felelnek meg a
¢
fenti szabálynak
a nyelv a kis és nagybet ket megkülönbözteti
35 36
Kiértékelési környezetek Lista skalár környezetben
@foo = (1..10);
Context
Lista környezetben a lista önmagára értékel dik ki
¢
Egy kifejezés értéke függ a kiértékelés helyét l
¢
Lista skalár környezetben az elemszámát adja
Környezetek
$bar = @foo;
Skalár:
¡
¡
¤
üres (void context)
¡
$bar == 10;
¤
logikai (boolean context)
¡
Eml:
operátor (operator context) $#foo: 9 (utolsó index)
¤
¤
Lista @foo skalár környezetben 10 (elemszám)
¤
¡
Hash környezet nincs Ez a lista lista környezetben értékel dik ki:
¢
¡
my ($bar) = @foo;
¡
$bar a lista els elemét tartalmazza
¢
¡
my ($bar, @rest) = @foo;
scalar: kiértékelés skalár környezetben
37
¡
print scalar(@foo); 38
contexts.pl
Skalár lista környezetben Hash
A skalár lesz a lista egyetlen eleme $hash{$_} = chr($_) for (48..57);
my @foo = $bar Lista környezetben a kulcs-érték párok
¡
¡
@foo: ($bar) felsorolásaként értékel dik ki ¢
my @foo = ($bar); Skalár környezetben a hash bels tárolásáról
¢
szolgáltat információt
Kulcsok számának meghatározása:
scalar(keys( %hash));
¡
39 40
undef.pl
Függvények viselkedése Skalár változók
Skalár:
Egy függvény viselkedése függhet a hívás helyét l
¢
wantarray függvény szám
¡
if (wantarray) => lista környezet szöveg
¡
if (!wantarray) => skalár környezet referencia
¡
if (!defined wantarray) => void context (skalár)
Nincs se lehet ség, se szükség a skalár típuson
¢
Pl: belüli különbségtételre
Számok és szövegek között automatikus konverzió
¡
if (defined wantarray) {
# bonyolult számítás elvégzése
Speciális skalár érték:
} undef
¡
logikailag hamis
¡
return wantarray ? @results : $results[0]; defined() operátorral vizsgálható egy skalár
¡
definiált volta
undef() operátor a nemdefiniált (undef) értéket
¡
41
adja 42
Számok Numerikus literálok
231847
Egy skalár kifejezésnek mindig van numerikus
12381.123
értéke
Ha a skalár egy sztringet tartalmaz, akkor az értéke
.42E+2
0 (de ez warning!)
1_000_000
¡
1 + 'alma' # 1 és egy warning
0xffff
0xdead_beef
¡
1+' 3 ' #4
0b10001001
undef: 0 (de ez warning!)
¡
1 + undef # 1 és egy warning
0644
Perl általában valósként kezeli a számokat
0b110_100_100
Ha ezek egy sztringben vannak, akkor
automatikusan csak decimális értékek
konvertálódnak
¡
hex('0xff')
43 ¡
oct('0755') 44
string-literals.pl
Sztringliterálok Sztringliterálok
' és “ között is megadható
q{}: nem helyettesít
¢
bash shellhez képest van különbség
qq{}: helyettesít
¢
¡
aposztróf escape-elhet aposztrófok között
¢
HERE dokumentum:
“ között változóhelyettesítés ¡
<<'END_HERE': nem helyettesít
¢
¡
variable interpolation ¡
<<”END_HERE”: helyettesít ¢
¡
double-quoted string
__DATA__ illetve __END__ után minden további
¡
“$var” sort figyelmen kív l hagy a fordító
¡
“${var}” ¡
a DATA (már megnyitott) filehandle segítségével
¡
“${var}::” kiolvashatjuk az adatokat onnan is
¡
“$var\::” ¡
utána close(DATA)
¡
“Price is \$100”
v52.50: '42'
skalár és tömb változókra (ill. hash slice-okra)
' között nincs változóhelyettesítés
¡
nincs \n, \t, stb. sem, de van \' 45 46
M veletek sztringekkel M veletek sztringekkel
chomp, chop uc, ucfirst:
$line = “example.pl\n”; uc('alma'): 'ALMA'
¡
chop($line): “example.pl” ¡
ucfirst('alma'): 'Alma'
¡
levágja az utolsó karaktert
lc, lcfirst:
¡
UNIX-okon rendben van (LF) ¡
lc('ALMA'): 'alma'
¡
MAC OS-n rendben van (CR) ¡
lcfirst('ALMA'): 'aLMA'
DOS/Windows: nincs rendben (CRLF) length('almafa'): 6
¡
chomp($line)
$greeting = 'Szia Peti! Isten hozott!';
¡
csak a sorvége jelet vágja le, de azt megfelel en
¢
¡
substr($greeting, 5, 4): 'Peti'
¡
minden OS-n megfelel ¢
¡
balérték!
substr($greeting, 5, 4) = 'Zsuzsi';
¤
47 48
Listák Lista konstruktorok
a zárójel opcionális, bár a precedencia szabályok
Elemei csak skalárok lehetnek
Els karakter mindig @
¢
miatt mindig érdemes használni
Például a @ARGV tartalmazza a program
a listaelemeket , választja el egymástól
(): üres lista (null list)
paramétereit
Egy lista megfelel elemének hivatkozása
¢
@foo = (1, 'abc', -12, 23.11);
Vigyázat:
Nem kell el re megadni a tömb elemszámát
¢
A listát kezelhetjük tömbként is, azaz tetsz leges
¢
$foo = (1, 'abc', -12, 23.11); # $foo == 23.11
¡
index elemét konstans id alatt elérhetjük
¢
@foo = (1, 'abc', -12, 23.11);
¡
$#list megadja az utolsó elem indexét $foo = @foo; # 4
@languages = (
scalar(@list) megadja a lista hosszát
A skalárok “altípusaira” nincs megkötés 'Hungarian',
'English',
'Italian',
49
); 50
Lista konstruktorok Lista konstruktorok: qw
ekvivalensek: Ezzel az operátorral szavak listáját hozhatjuk
¡
@range = (1,2,3,4,5); könnyen létre
¡
@range = (1..5);
a következ k ekvivalensek
¢
ekvivalensek my @months = qw(Jan Feb Mar Apr);
¡
¡
@chars = ('a', 'b', 'c', 'd', 'e', 'f'); ¡
my @months = ('Jan', 'Feb', 'Mar', 'Apr');
@chars = ('a'..'f'); fehér szóközöknél vág
¡
s t: @a_pairs = ('aa'..'az'); # aa, ab, ac, ad, ...
¢
ekvivalensek:
¡
@numerals = ('one', 'two', 'three', 'four');
¡
@numerals = qw(one two three four);
51 52
Listák kiegyenesítése Szimultán értékadás
Abból, hogy csak skalárokat tartalmazhat, értékadás bal oldalán is állhat lista
következik ez a viselkedés teljes lista helyettesítése:
@num_list = (1,2,3,4); ¡
@foo = ('a', 'b');
@char_list = ('a', 'b', 'c', 'd');
@foo = (1, 2, 3, '#');
@lists = (@num_list, @char_list);
($one, $two) = @foo;
az új lista nem két listát, hanem 8 skalárt tartalmaz $one, $two = @foo;
¡
¡
eredmény: $one undef, $two = 4;
¡
ui:
$one, ($two = @foo);
¤
($one, $two, @rest) = @foo;
csere szimultán értékadással:
¡
($a, $b) = ($b, $a);
53 54
localtime Lista elemeinek elérése
skalár környezetben @hex = ('a'..'f', 'A'..'F');
print scalar(localtime); $hex[0]; # 'a'
¡
¡
Sat Jan 17 22:34:49 2004
$hex[-1]; # 'F'
lista környezetben 9 elem listát ad vissza
$hex[$#hex]; # 'F'
¡
perldoc -f localtime
szeletek (slices): a tömb egy részének kiválasztása
sec, min, hour, mday, mon, year, ... ez a rész is tömb
¡
ha csak az óra, a nap és a hónap érdekel: @hex[0..5] # kisbet k
¡
(undef, undef, $h, $day, $mon) = localtime(); @hex[0,6] # 'a' és 'A'
¡
Ennek megfelel en:
¢
¡
($year, $month, $day) = (localtime())[5,4,3];
55 56
M veletek listákkal M veletek listákkal
pop: a lista végér l kivesz egy elemet push és unshift egy listát vár
¢
push: a lista végére helyez egy elemet push(@nums, 1..10);
¡
shift: a lista elejér l kivesz egy elemet
¢
push(@nums, 50..55);
unshift: a lista elejére helyez egy elemet push(@nums, -1, -2, -10, -57);
lista veremként kezelése:
@nums = (1, 2);
pop és push push(@nums, 3..5);
¡
lista sorként kezelése: @nums; # (1, 2, 3, 4, 5);
¡
¡
shift és push
unshift(@nums, -2..0);
¡
pop és unshift ¡
@nums; # (-2, -1, 0, 1, 2, 3, 4, 5);
lista közepe is módosítható a splice függvénnyel splice
¡
my @list = qw(a b c d);
¡
splice(@list, 1, 0, 'á');
57 58
M veletek listákkal join és split
my $top = pop(@nums); Egy lista elemei összef zhet ek egy sztringbe
¢
¡
$top; # 5 ¡
@names = ('Peti', 'Andi', 'Kata');
¡
@nums; # (-2, -1, 0, 1, 2, 3, 4); ¡
join(', ', @names); # Peti, Andi, Kata
my $first = shift(@nums);
Egy sztring szétszedhet listába:
¢
¡
$first; # -2 ¡
$codes = '34:52:a9:9e:5f';
¡
@nums; # (-1, 0, 1, 2, 3, 4); ¡
my @codes = split(':', $codes);
top függvény nincs @codes; # ('34', '52', 'a9', '9e', '5f');
¡
¡
$nums[$#nums]; # 4
59 60
Hash-ek Kulcsok és értékek
Kulcs érték párok Egy hash kulcsai elérhet ek a keys operátor
¢
Kulcs szám vagy szöveg lehet segítségével
Érték csak skalár lehet (szám, szöveg, referencia) ¡
keys(%hash)
%hash = ( ¡
ez egy lista, a kulcsok sorrendje nem definiált
'date' => '2004-01-10',
Egy hash értékei elérhet k a values operátor
¢
'wheather' => 'rainy', segítségével
); ¡
values(%hash)
Adott kulcsú elem elérése: ez is lista, az értékek sorrendje nem definiált
¡
$hash{'date'} ¡
a sorrend megegyezik a kulcsok sorrendjével
A kulcsot nem kell mindig aposztróf közé tenni
A tárolás nem tartalmaz információt az elemek
sorrendjére vonatkozóan
61 62
Értékek vizsgálata Hash és listák
defined $hash{'key'} Egy hash lista környezetben a kulcsok és értékek
¡
igaz, amennyiben az érték definiált listájává értékel dik ki ¢
exists $hash{'key'} ¡
%hex_codes = (
¡
igaz, ha létezik ilyen kulcs a hash-ben 'a' => 10, 'b' => 11, 'c' => 12,
¡
különbség, ha az érték undef 'd' => 13, 'e' => 14, 'f' => 15,
%hash = ( );
'key' => undef, ¡
utolsó vessz nem typo
¢
); ¡
@list = %hex_codes;
defined $hash{'key'} az eredmény valami ilyesmi:
¤
hamis ('e', 14, ' c', 12, 'a', 10, 'b', 11, 'd', 13, 'f', 15)
¤
¡
exists $hash{'key'}
¡
igaz
63 64
Hash és listák Hash szeletek
Egy listával is feltölthetünk egy hash-t
Egy hash egy szelete az értékeinek egy listája
%hex_codes = @list;
%hex_codes = (sorrend van!)
('a', 10, 'b', 11, 'c', 12, 'd', 13, 'e', 14, 'f', 15);
@hex_codes{'c', 'b', 'a'}
Akár egy kifejezés eredménye is lehet:
¡
(12, 11, 10);
%hex_codes = map { $_, ord($_)-87 } 'a'..'f';
¡
Ez balérték is:
%hex_codes: (
¡
¡
@hex_codes{'c', 'b', 'a'} = (12,11,10);
'a' => 10,
¡
@hex_codes{'c', 'b', 'a'} = (12,11);
$hex_codes{'a'} undef lesz
¤
'b' => 11,
A következ kifejezés például ugyanazt
¢
'c' => 12,
eredményezi, mint a values operátor:
'd' => 13, ¡
@hex_codes{keys %hex_codes};
'e' => 14,
'f' => 15,
) 65 66
Feltételek Feltételek
"0" # hamis Listák is kiértékel dhetnek logikai környezetben
¢
"0.0" # igaz, mert nem a '0' sztring Egy listaváltozó akkor értékel dik ki igazra, ha a
¢
0.0 # hamis, mert konvertálódik, és "0" lesz lista nem üres
bel le, ami hamis
¢
Egy ,-s kifejezés ilyenkor az utolsó értéket adja
00 # hamis
@list = ();
0.01 # igaz print “TRUE” if @list; # hamis
"00" # igaz @list = (0);
{} # igaz, mert ez egy referencia print “TRUE” if @list; # igaz
[] # igaz, mert ez egy referencia
De:
undef # hamis print “TRUE” if (0); # hamis
print “TRUE” if (); # hamis
print “TRUE” if (1); # igaz
67
print “TRUE” if (1, 0); # hamis 68
Elágazások Feltételek hátul
Tetsz leges kifejezés szerepelhet feltételben
¢
A feltétel hátul is lehet, mind if, mind pedig unless
Csak a 0, '' (üres sztring), undef hamis
Ilyenkor a feltétel zárójelek közé zárása nem
if (feltétel) {
kötelez¢
...
print 'Connecting...' if $verbose;
}
die 'Cannot connect' unless defined $connection;
elsif (feltétel) {
...
}
else {
...
}
unless (feltétel) {
...
} 69 70
Hibakezelés Hibakezelés
Feladat Írhatnánk ezt is:
próbál kapcsolódni my $conn;
¡
¡
ha sikerül, folytassa a munkát unless (defined $conn = get_connection()) {
¡
ha nem sikerül, lépjen ki hibával die “Cannot connect: $!\n”;
Így írnánk meg: }
my $conn = get_connection(); # do the work
unless (defined $conn) { De van más mód is
die “Cannot connect: $!\n”;
Lusta kiértékelés
} ¡
and, or operátorok használhatóak hiszen az
# do the work értékadás is kifejezés
¡
&&, || is használhatóak, de ezeknek magasabb a
precedenciájuk
71 72
Hibakezelés and példa
my $conn = get_connection() fork and exit;
or die “Cannot connect: $!\n”; ¡
probléma: nem kezeli, ha sikertelen a fork
El nyei:
¢
my $pid = fork and exit;
¡
tömör die “Cannot fork: $!\n” unless defined $pid;
¡
olvasható ¡
mivel az and precedenciája kicsi, ezért
¡
látszik a lényeg, nevezetesen, hogy kapcsolódni tökéletesen m ködik
szeretnénk ¡
(my $pid = fork) and exit;
de közben korrekt hibakezelés is van my $pid = fork && exit;
¡
¡
Perl-es :) ¡
az && operátor precedenciája nagyobb, ezért
ezt jelenti:
my $pid = (fork && exit);
¤
¡
helyette:
73
¡
(my $pid = fork) && exit; 74
list_manip.pl
?: operátor Ciklusok
list_manip_better.pl
ismer s C-b l while (feltétel) {
¢ ¢
feltétel ? igaz_ág : hamis_ág; ...
defined $param ? print “OK” : print “NOT OK”; }
Ez kifejezés until (feltétel) {
print(defined $param ? “OK” : “NOT OK”); ...
¡
a zárójel elhagyható lenne a precedencia- }
szabályok miatt for (init kif; feltétel kif; növ kif) {
Ami érdekes, hogy az eredmény balérték is lehet. ...
(is_left() ? $left : $right) += 1; }
a zárójel elhagyható lenne a precedencia- foreach $element (@list) {
¡
szabályok miatt ...
}
75 76
Ciklusok Hátultesztel “ciklusok”
£
Egy ciklus iterációjának közepén is terelhetjük do BLOCK
másfele a vezérlést végrehajtja a megadott blokkot és az utolsó
¡
last: kilépés a ciklusból kifejezés értékét visszaadja
while (my $line = <STDIN>) {
ez utasítás, ezért használhatunk
last if $line =~ /^\.$/; utasításmódosítókat hozzá
... do {
} $lines++;
print “[$lines] $line\n”;
¡
next: következ iterációra lépés
¢
} if $print_the_lines;
while (my $line = <STDIN>) { do {
next if $line =~ /^#/; $lines++;
... print “[$lines] $line\n”;
} 77 } while $lines < N; 78
Hátultesztel “ciklusok” Hátultesztel “ciklusok”
£ £
a do nem ciklus
a fapados megoldás:
nem használhatók a ciklusvezérl utasítások: next,
¢
while (1) {
redo, last
alternatív lehet ségek
¢
....
do {{ last if $x == $y;
next if $x == $y; }
$\ = “\n”;
...
}} until $x++ > $z; my $n = 0;
for (;;) {
LOOP: { print $x++;
do { last if $x > 10;
last if $x == $y**2; }
} while $x++ < $z;
} 79 80
redo.pl
Ciklusok: redo Ciklusok: continue
redo: az adott iteráció újrakezdése a continue blokk közvetlenül a következ iteráció
¢
Egy szó visszaszámlálása: el tt fut le
¢
while ( my ($line) = (<STDIN> =~ /^(.*)\n$/) ) {
next hívásakor például ebbe ugrik
print "$line\n"; redo, last kihagyja
chop($line);
while (my $line = <STDIN> ) {
redo if length($line); ...
} } continue {
Hibás a $line scope-ja miatt $not_empty = 1;
}
81 82
Listák bejárása Hash-ek bejárása
Egy lista elemeit bejárhatjuk az indexei szerint Egy hash összes kulcsán illetve értékén
(tömbként kezelés) végigiterálhatunk
for (my $i=0; $i <= $#list; $i++) {
keys(%hash) eredménye egy lista, ezen pedig már
# $list[$i] feldolgozása végig tudunk haladni
}
foreach my $key ( keys %hash ) {
Jobb megoldás, ha a foreach ciklust használjuk # ($key, $hash{$key}) pár feldolgozása
foreach my $element ( @list ) { }
# $element feldolgozása
Ha csak az értékekre van szükségünk:
} ¡
values %hash
Az utóbbi módon nem értesülünk az elem ennek az eredménye is lista
¡
sorszámáról, de erre általában nincs is szükség foreach my $value ( values %hash ) {
# $value feldolgozása
83
} 84
Hash: kulcs-érték párok
Egy hash összes kulcs-érték párján is
végigiterálhatunk
each
Alprogramok
while (my ($key, $value) = each %hash) {
# ($key, $value) pár feldolgozása
}
Hogy ez m ködjön, minden hash-hez kell egy
bels mutató, ami a következ elemre mutat
¢ ¢
Ez újra az els elemre fog mutatni, ha egyszer
¢
végigért egy iteráció
a keys, values operátorok inicializálják ezt a
mutatót
85 86
hello_sub.pl
Alprogramok Alprogramok hívása
Alprogramok a sub kulcsszóval deklarálhatók Egy egyszer alprogram:
Lehetséges el re deklarálni egy eljárást sub NAME BLOCK
¢
Alprogramok hívása olyan, mint a beépített
sub hello {
parancsok használata print “Hello world!\n”;
¡
zárójelek opcionálisak is lehetnek }
általában azért érdemes kitenni egy alprogram hívása:
¡
Formális paraméterek nem adhatóak meg NAME;
¡
Utolsó kiértékelt kifejezés értéke lesz a visszatérési zárójel csak akkor hagyható el, ha az alprogram el re
¤
érték definiált, vagy importált
Egy alprogramhívás történhet lista, skalár vagy
¡
NAME();
üres környezetben (list, scalar, void context)
¡
&NAME;
¡
&NAME();
hello();
87 88
Alprogramok: paraméterek Alprogramok: paraméterek
Nem definiálhatunk formális paramétereket sub print_message {
Ilyen forma nem használható: print “Message to $_[0]: $_[1]\n”;
¡
sub print_message($to, $message) { }
....
print_message('Andi', 'Este randi?');
}
sub write_capital {
A paraméterek egy egyszer listában kerülnek foreach my $name (@_) {
átadásra print ucfirst($name), ', ';
Ez a lista az @_ lista }
¡
$_[0] az els paraméter
¢
print “\n”;
¡
$_[1] a második paraméter }
stb. write_capital('andi', 'gabi', 'peti');
¡
¡
Andi, Gabi, Peti,
89 90
Alprogramok: paraméterek Alprogramok: paraméterek
Ez is jó: sub pretty_print {
my @names = ('andi', 'laci', 'zsuzsa'); foreach my $param ( @_ ) {
write_capital(@names); print “>>$param<<\n”;
Andi, Laci, Zsuzsa,
¡
}
A Perl kiegyenesíti a paramétereket az @_ listába }
Ezért ez is teljesen jól megy: A következ hívásnak nincs értelme:
¢
@boys = ('peti', 'zoli', 'feri'); pretty_print(@list, %hash, $scalar);
@girls = ('juci', 'mari', 'kati'); ¡
minden paraméter az @_ listába kerül
write_capital(@girls, @boys); ¡
a Perl kiegyenesíti a listákat
Juci, Mari, Kati, Peti, Zoli, Feri, tehát nem három paramétere lesz, hanem @list
¡
elemszáma plusz %hash kulcsai számának
duplája plusz 1
91 92
Alprogramok: paraméterek Alprogramok: paraméterek
Egy hosszabb eljárásban az @_ tömbön keresztül @_ az alapértelmezett tömb, ha nincs megadva
hivatkozni a paraméterekre kényelmetlen és nem semmi, akkor ezt kezeli a shift
jó sub print_messages {
¡
Ötlet: shift-elhetünk bel le my $to = shift;
¢
sub print_messages { print “Message to $to\n”;
my $to = shift(@_); my $first_message = shift;
print “Message to $to\n”; print “\t[1] $first_message\n”;
my $first_message = shift(@_); my $count = scalar(@_);
print “\t[1] $first_message\n”; print “\t$count more message(s)\n”;
my $count = scalar(@_); }
print “\t$count more message(s)\n”;
zavaró, és könny elrontani, ha módosítunk a
} kódon
93 94
Alprogramok: paraméterek Alprogramok: paraméterek
my deklarációk segítségével az alprogramban él
¢
sub mysub {
változókat használhatunk a paraméterek my ($param_1, $param_2, @rest) = @_;
nevesítésére ...
sub mysub { }
my ($param_1, $param_2) = @_;
@_ lista:
... ¡
ha üres, akkor mindkett változó értéke undef
¢
} lesz, a lista pedig üres
@_ lista: ¡
ha 1 elem , akkor csak $param_2 lesz undef,
ha üres, akkor mindkett változó értéke undef
¢
valamint a lista üres
¡
lesz ¡
ha 2 elem , akkor egyik sem lesz undef, de a
¡
ha 1 elem , akkor csak $param_2 lesz undef
lista üres lesz
¡
ha 2 elem , akkor egyik sem lesz undef
¡
ha több elem , akkor a többi paraméter a
¡
ha több elem , akkor a többi paraméter 'elvész',
listába kerül
az alprogram nem használja ket¢
95 96
Alprogramok: default
Alprogramok: paraméterek
paraméterek
Átadott paramétereknek default értéket nem
sub print_messages {
¡
my ($to, $first, @rest) = @_; adhatunk
Van rá mód, hogy ezt megkerüljük
print “Message to $to\n”; sub log_message {
print “\t[1] $first\n”; my ($message, $level) = @_;
my $count = scalar(@rest); $level = defined $level ? $level : 'INFO';
print “\t$count more message(s)\n”; ...
} }
kicsit jobb, ha:
¡
sub log_message {
my ($message, $level) = @_;
$level = 'INFO' unless defined $level;
...
97
} 98
Alprogramok: default
Alprogramok: visszatérés
paraméterek
De ez is jó: A visszatérési érték is egy lista lehet
sub log_message {
¡
Ha két listát adnánk vissza, akkor azok
¡
my ($message, $level) = @_; kiegyenesít dnek
¢
$level = $level || 'INFO'; Természetesen a lista lehet egyelem is
...
Az utolsó kiértékelt kifejezés értéke lesz a
} visszatérési érték
Vagy tömörebben és olvashatóbban: Explicite megadható a return utasítással is
sub log_message {
¡
Ha nem adunk meg visszatérési értéket, akkor
¡
my ($message, $level) = @_; skalár környezetben undef, lista környezetben
$level ||= 'INFO'; pedig üres lista lesz a visszatérési érték
...
}
99 100
Alprogramok: visszatérés Alprogramok: visszatérés
sub succ {
Természetesen rekurzió is van Perlben
my ($num) = @_;
sub fact {
$num + 1; my ($n) = @_;
} return 1 if $n <= 1;
$nat = 0; return $n * fact($n - 1);
$nat = succ($nat) while 1; }
A fenti eljárásba az olvashatóság kedvéért érdemes
my $fact_of_3 = fact(3); # 6
egy return-t tenni
sub succ {
my ($num) = @_;
return $num + 1;
}
vagy teljesen lerövidítve:
¡
sub succ { $_[0] + 1 } 101 102
Alprogramok: visszatérés Alprogramok: visszatérés
Visszaadhatunk listát is Ha egy alprogamot más környezetben hívunk,
sub stepped_range { akkor más is lehet az eredmény
my ($start, $end, $step) = @_;
my $results = stepped_range(10, 20, 3);
my @result = (); ¡
az eredmény lista négy elem
for (my $i = $start; $i <= $end; $i += $step) { ¡
ennek kiértékelése skalár környezetben a lista
push(@result, $i); elemszámát adja
} ¡
$results; # 4
return @result;
}
my @list = stepped_range(10, 21, 3);
¡
(10, 13, 16, 19)
103 104
Alprogramok: listák Alprogramok: wantarray
sub inc { Eldönthet , hogy az eljárást milyen környezetben
¢
my (@numbers) = @_; hívták
wantarray függvény
my @result = (); ¡
hamis, ha skalár környezetben
foreach my $number ( @numbers ) { ¡
igaz, ha lista környezetben
push(@result, $number + 1); ¡
undef, ha üres környezetben (void context)
}
El z inc
¢ ¢
my $result = inc(1); # 1
return @result;
helyesen:
} my ($result) = inc(1); # 2
my @inced = inc(@nums); könny elrontani
¡
my (@odds, @evens) = inc(@evens, @odds); ¡
kényelmetlen
hibás, az eredmény lista is kiegyenesít dik
¢
¡
105 106
Alprogramok: wantarray Alprogramok: wantarray
Kihasználhatjuk még, hogy üres környezetben
sub inc {
(void context) a wantarray undef-t ad
my (@numbers) = @_;
sub my_sub {
...
my @result = ();
return unless defined wantarray;
foreach my $number ( @numbers ) {
push(@result, $number + 1);
# m veletigényes számítások
}
...
return wantarray ? @results : $result[0];
return wantarray ? @result : $result[0];
}
}
Ha nem használjuk fel az eredményt, akkor el sem
Lista környezetben visszaadja az egész listát
végzi a számításokat
Skalár környezetben csak az els elemet
¢
Minden korábbi formával m ködik
107 108
Alprogramok: prototípusok Alprogramok: prototípusok
A paraméterátadás szintaxisa és szemantikája sub add($$) {
miatt semmiféle ellen rzés nincs a paraméterek
¢
return $_[0] + $_[1];
számára és típusára vonatkozóan }
Ezt egy kicsit szigoríthatjuk
két skalárt vár
Prototípusok: fordítási idej ellen rzés
¢
add(12, 13);
Nem teljeskör , nincs lehet ség elnevezni a hibás hívások
¢
paramétereket ¡
add(1);
Rövid leírás egy függvény paramétereinek típusára add(1,2,3);
¡
illetve számára vonatkozóan ¡
add(@numbers)
ahol @numbers: (1,2)
¤
szintaktikailag helyes:
¡
add(@numbers, $scalar);
109
¡
lista kiértékel dik skalár környezetben
¢
110
prototypes.pl
Alprogramok: prototípusok Alprogramok: prototípusok
$: skalárt várunk Referenciák használatával az átadott
@: listát várunk paramétereket közvetlenül módosíthatjuk
%: hash-t várunk
A Perlben eddig megszokottól eltér en viselkedhet
¢
&: kódot várunk egy függvényhívás
*: elfogad typeglobot is, skalárt, konstanst,
sub fill(\@$);
bareword-t ¡
a paraméterül adott tömböt módosíthatja
\ karakterrel az eljárás már referenciát kap a függvény egy referenciát kap a tömbre
¡
; -vel jelezhetünk opcionális paramétereket
alternatívákat a \[] jelöléssel adhatunk meg
111 112
correctness.pl
Alprogramok: prototípusok Alprogramok: prototípusok
& paraméterrel akár látszólag új szintaxist is a függvény hívása:
teremthetünk transaction {
az átvett paraméter egy szubrutin referencia # DB inserts...
sub transaction(&) {
my ($codes) = @_; # DB deletes...
};
eval { lényeges és kötelez a pontosvessz
¢ ¢
&$codes;
};
if ($@) { $dbh->rollback(); }
else { $dbh->commit(); }
} 113 114
constants.pl
Alprogramok: konstansok Alprogramok: konstansok
konstansként kezeltek a paraméter nélküli Ilyen célra a constant modult érdemes használni
prototípussal definiált alprogramok, ha a use constant PI => 4 * atan2(1,1);
szemantikájuk ezt lehet vé teszi
¢
use constant DEBUG => 0;
a következ k konstansként viselkednek
¢
use constant NAPOK => (
¡
sub PI() { 3.14159 } 'Hétf ', 'Kedd', 'Szerda', 'Csütörtök',
¢
¡
sub FLAG_READ () { 1 << 2 } 'Péntek', 'Szombat', 'Vasárnap',
¡
sub FLAG_WRITE () { 1 << 1 } );
sub FLAG_EXECUTE () { 1 } use constant NAPOK => qw(
¡
¡
sub DIR_PERM () { Hétf Kedd Szerda Csütörtök
¢
FLAG_READ | FLAG_EXECUTE Péntek Szombat Vasárnap
} );
a csupa nagy bet s név konvenció, nem kényszer
115 116
enclosing_subs.pl
Alprogramok egymásban Privát változók
my operátorral deklarált változók
Elvileg lehetséges alprogramokat egymásba
lokális a tartalmazó blokkra, eval-ra vagy file-ra
ágyazni
Gyakorlatilag problémákat vet fel nézve
lexikálisan privát
Egy alprogram definiálása az aktuális
környezetben történik
ha a strict modult használjuk, akkor
A bels alprogram nem használja a tartalmazó
¢
mindenképpen szükséges deklarálni minden
alprogram változóit változót valamilyen módon
a továbbiakban feltesszük, hogy használjuk a strict
¡
warning: ... will not stay shared...
modult
my $x;
¡
$x értéke undef lesz
my $x = 10;
¡
$x inicializálva a 10 értékre
117 ¡
$x lexikálisan privát 118
Privát változók Privát változók
Ha egyszerre több változót szeretnénk deklarálni, my ($foo) = <STDIN>;
akkor zárójelek közé kell tenni ¡
a kifejezés lista környezetben értékel dik ki
¢
my $x, $y;
my @foo = <STDIN>;
¡
hibás, $y nem ismert ¡
szintén
¡
végrehajtásilag ugyanaz, mint:
my $foo = <STDIN>;
my $x; skalár környezetben
¤
¡
$y;
A következ sortól kezdve lesz deklarált a változó
¢
my ($x, $y); my $x = $x;
Inicializálás lehetséges listával: csak akkor érvényes kifejezés, ha a $x már
¡
¡
my ($x, $y) = (10, 12); ismert volt
119 120
Privát változók Privát változók elágazásban
Egy alprogramban a deklarálás helyét l az Szintén a deklaráció helyét l az elágazás végéig
¢
¢
alprogram végéig látható egy my változó érvényes
sub subroutine {
Ha a feltételben inicializáljuk, akkor az egész
my ($arg1, $arg2) = @_; elágazáson át látható a változó
... if ((my $answer = lc(<STDIN>)) eq ”yes\n”) {
my $sum = $arg1 + $arg2; user_agrees();
... } elsif ($answer eq ”no\n”) {
} user_disagrees();
Kív lr l nem érhet el
¢ ¢
} else {
Nem min síthet az alprogram nevével
¢ ¢
chomp $answer;
¡
tehát pl. nincs ilyen: $subroutine::sum, vagy die "'$answer' is neither 'yes' nor 'no'";
hasonló }
121 122
Privát változók elágazásban Privát változók ciklusokban
Hátracsapott feltétel esetén a láthatóság nem while (my $line = <STDIN> ) {
definiált chomp($line);
Bár jelenleg a láthatósága kiterjed az egész blokkra, ...
evalra, file-ra, a kés bbi verziók ezt viselkedést }
¢
megváltoztathatják
continue blokkban is látható a my változó
my $line = <STDIN> if $read_next_line; for ciklusban a ciklus végéig látható
¡
nem helyes ¡
for (my $i = 0; $i < 10; $i++) {
my $line; ...
$line = <STDIN> if $read_next_line; }
helyes foreach ciklus esetén szintúgy
¡
¡
foreach my $element ( @list ) {
...
123 } 124
Privát változók élettartama local
my változók lexikális láthatóságát a tartalmazó Minden változó, mely nem my, globális
blokk határozza meg A my ezt a nem túl rugalmas viselkedést
élettartamuk lehet szélesebb is ennél szabályozza
akkor szabadul fel, ha már nincs rá hivatkozás
a local elmenti a változó értékét, és egy blokkra
vonatkozó lokális értéket ad neki
{
local $SIG{'INT'} = 'IGNORE';
func();
}
125 126
local.pl
local
{
local $dbh->{'RaiseError'} = 0;
$dbh->do(q{
UPDATE salaries
SET salary += salary * 0.10
});
}
{
local STDERR = *STDOUT;
print STDERR “...”;
}
127
Related docs
Get documents about "