_  _   ,_
/^\/^\-/ @D
~(________/ PERL.LT
|L |L
L L
Straipsniai  Funkcijos 
Funkcijos/eval - sugaudo klaidas arba sukompiliuoja ir paleidžia kodą
  • eval EXPR
  • eval BLOCK

    Pirmuoju atveju, EXPR grąžinta reikšmė yra suparsinama ir įvykdoma tarsi būtų maža Perl programėlė. Išsireiškimo reikšmė (kuri savaime yra apsprendžiama esanti skaliariniame kontekste) pirmiausia suparsinama, o jei buvo klaidų, įvykdoma vykdomos Perl programos žodyniniame kontekste, taip, kad bet kokie kintamųjų nustatymai ar paprogramės ir formatų apibrėžimai, pasilieka už jos. Pažymėtina, kad reikšmė yra suparsinama kas kartą kai vykdomas šis eval. Jei EXPR praleistas, lyginamas $_ . Ši forma dažniausia naudojama kad atidėti parsinimą ir po to sekantį EXPR teksto vykdymą iki paleidimo.

    Antruoju atveju, kodas BLOCK'e suparsinamas tik vieną kartą - tuo pačiu metu kodas apie eval pats yra suparsinamas ir įvykdomas tos pačios Perl programos kontekste. Ši forma dažniausiai naudojama kur kas sėkmingiau aptikti išimtis nei pirmoji (žr. žemiau), tuo pačiu pratikrinant kodą BLOCK'e kompiliavimo metu.

    Galutinis kabliataškis, jei toks yra, gali būti praleistas iš EXPR reikšmės arba iš BLOCK'o.

    Abiem atvejais, grąžinta reikšmė yra paskutinio išsireiškimo reikšmė, sulyginta mini-programoje; grąžinimo sakinys (return) taip pat gali būti naudojamas kaip ir su paprogramėmis. Išsireiškimas, duodantis grąžinamą reikšmę yra prilyginamas void, skaliariniame ar sąrašo kontekste, priklausomai nuo to, kokiame kontekste yra tvarkomąsi su eval. Žr. wantarray dėl daugiau inormacijos kaip prilyginimo kontekstas gali būti nustatomas.

    Jei pasitaiko sintaksės ar vykdymo klaidų ar įvykdomas die sakinys, eval, grąžina neapibrėžtą reikšmę, o į $@ įrašoma klaida. Jei klaidų nebuvo, $@ yra tuščia seka. Turėkite omeny, kad naudojant eval nei nutildo perlą nuo įspėjimų išvedimo į STDERR, nei sukiša įspėjimus į $@ . Norint kurio nors iš pastarųjų variantų, reikia naudoti $SIG{__WARN__} sąlygą arba išjungti pranešimus BLOCK'e ir EXPR naudojant no warnings 'all'. Žr. warn, perlvar, warnings ir perllexwarn.

    Įsiminkite tai, nes eval pagauna kitais atžvilgiais lemtingas klaidas, jis naudingas apsprendžiant ar tam tikros savybės (kaip kad socket ar symlink) yra realizuotos. Tai taip pat yra ir Perl išimčių aptykimo mechanizmas, kur die operatorius naudojamas prieštaravimų aptikimui.

    Jei kodas, kuris bus vykdomas, nesikeičia, galima naudoti eval-BLOCK formą sugaudyti vykdymo klaidas neperkompiliuojant kiekvieną kartą. Klaida, jei tokia yra, grąžinama $@ . Pavyzdžiai:

        # Mėginame su dalyba iš nulio - ne "fatal"
        eval { $answer = $a / $b; }; warn $@ if $@;
        # tas pats, bet ne taip efekyvu
        eval '$answer = $a / $b'; warn $@ if $@;
        # kompiliavimo klaida
        eval { $answer = };			# NETEISINGA
        # vykdymo klaida
        eval '$answer =';	# užsetina $@

    Ryšium su dabartiniu be abejonės sugadintu __DIE__ , naudojant eval{} formą prieštaravimų ieškojimui bibliotekose, greičiausia bus norima nepaleisti __DIE__ , kurį vartotojas kode greičiausia bus jau instaliavęs. Galima naudoti local $SIG{__DIE__} konstrukciją šiam reikalui, kaip parodyta pavyzdyje:

        # labai neviešas prieštaravimas dėl dalybos iš nulio
        eval { local $SIG{'__DIE__'}; $answer = $a / $b; };
        warn $@ if $@;

    Tai ypač matyti, turint omeny, kad __DIE__ gali vėl iškviesti die , kuris gali pakeisti klaidų pranešimus:

        # __DIE__ gali keisti pranešimus apie klaidas
        {
           local $SIG{'__DIE__'} =
                  sub { (my $x = $_[0]) =~ s/foo/bar/g; die $x };
           eval { die "foo lives here" };
           print $@ if $@;                # išveda "bar lives here"
        }

    Dėl tokio veikimo, jo neintuityvi elgsena gali būti pakeista ateities leidimuose.

    Su eval, reikėtų būti ypač atsargiems prisiminti, kaip atrodė:

        eval $x;		# 1
        eval "$x";		# 2
        eval '$x';		# 3
        eval { $x };	# 4
        eval "\$$x++";	# 5
        $$x++;		# 6

    1 ir 2 atvejas veikia identiškai: jie vykdo kodą, kuris yra kintamąjame $x. (Nors 2 atveju yra klaidinančios kabutes, kurios gali priversti susimąstyti - o kas gi bus (nieko).) 3 ir 4 atvejis panašiai elgiasi: jie vykdo '$x' kodą, kuris nieko nedaro, tačiau grąžina $x reikšmę. (4 atvejis labiau priimtinas vien dėl vizualių priežasčių, bet taip pat turi pranašųumą, kad yra sukompiliuojamas kompiliavimosi metu, o ne paleidimo.) 5 atvejis yra tas, kur normaliai norėtųsi panaudoti dvigubas kabutes, tik kad šioje situacijoje galima tiesiog naudoti to vietoje simbolines nuorodas, kaip ir 6.

    eval BLOCK nevykdo skaičiavimų kaip kad ciklas, taigi ciklo kontrolės sakiniai kaip next, last, ar redo negali būti naudojami kad palikti ar iš naujo įeiti į bloką.

    Pažymėtina, kad ypač specialiu atveju eval '' vykdomas DB pakete, nemato įprastinio žodyno, bet mato pirmo ne-DB gabalo kodą, iš kurio jis buvo pakviestas. Dažniausia dėl to nereikia jaudintis, nebent yra rašomas Perl debugeris.

algirdas@perl.lt 2005.04.11 - $dabar