PHP::Strings

Paskutinėmis praeitų metų dienomis staiga mirė vienas iš Perlo programuotojų, perlreref autorius (lietuviškas vertimas
čia) Iain „Spoon“ Truskett. Jam tebuvo tik 24 metai.

Taip viskam atsitikus, liko keletas jo CPAN modulių, ir Perlo bendruomenė pradėjo rūpintis, kad jie nebūtų apleisti. Vienas modulis patraukė mano dėmesį, nes panašių minčių turėjau ir aš. Tai PHP::Strings, kuriuo implementuojama daugelis PHP funkcijų Perlu. Pasisiūliau jį prižiūrėti, jei neatsiras kas nors labiau patyręs ;-)

Pačiame modulyje yra keletas įdomių nuorodų, kur aprašomi PHP trūkumai, štai jie:

  • http://tnx.nl/php.txt
  • http://www.webkreator.com/php/community/php-love-and-hate.html
  • http://keithdevens.com/weblog/archive/2003/Aug/13/HATE-PHP
  • http://n3dst4.com/articles/phpannoyances/
  • http://www.ukuug.org/events/linux2002/papers/html/php/
  • http://czth.net/pH/PHPSucks
  • http://www.nntp.perl.org/group/perl.advocacy/1458
  • http://www.gnu-friends.org/story/2002/5/29/113829/681

Asmens::Kodas

The URL

http://moxliukas.esu.as/download/src/Perl/Asmens-Kodas-0.01.tar.gz

has entered CPAN as

file: $CPAN/authors/id/K/KU/KUDARASP/Asmens-Kodas-0.01.tar.gz

  size: 1859 bytes

   md5: 14269ea9efca41e0559951ac20152858

No action is required on your part

Request entered by: KUDARASP (Petras Kudaras)

Request entered on: Mon, 29 Dec 2003 09:07:23 GMT

Request completed:  Mon, 29 Dec 2003 09:09:13 GMT

Thanks,

-- paused, v460

Reikės dar padaryt normalesnį datų tikrinimą Asmens kodui :/

Perthon

Va ką šiandien užtikau:

Posted today on PerlMonks was an interesting tool. Eventually, I
hope you Python monkeys will come to your senses and turn to Perl
for sanity. To ease such transition, see the Perthon project:


/http://perthon.sourceforge.net

Now, your Python code can be reborn as the Perl it always should
have been.

Komentarų turbūt nereikia ;-) Šiaip įdomus projektukas (bet kaip
ir dauguma kalbų vertėjų turbūt nelabai pritaikomas praktikoje)

Perlo objektai: antra dalis

Pagalvojimai apie ateitį: geresni konstruktoriai

Nors šiuo metu dar gal ir nežinote kas yra paveldimumas, bet kažkada
ateityje matyt teks su tuo susidurti. Tam, kad

paveldimumas veiktų kaip turėtų, reikia naudoti bless() su
dviem argumentais. Antruoju argumentu yra

perduodama klasė, į kurią bus „palaiminama“.

Tuo pačiu padarysime konstruktorių lankstesnį, kad būtų jį galima
iškviesti tiek kaip klasės, tiek kaip ir objekto

metodą. T.y. kad būtų galima rašyti:

$as = Asmuo->naujas();
$ji = $as->naujas();

Viskas ką mums reikia padaryti, tai patikrinti ar į konstruktorių
buvo perduota nuoroda (reference) ar ne.

Funkcija buvo iškviesta kaip objekto metodas jeigu buvo
perduota nuoroda – tokiu atveju reikia

sužinoti kas tai per klasė naudojantis funkcija ref(). Jei
perduota ne nuoroda, o paprasčiausias klasės

pavadinimas, tai juo ir naudojamės (tokiu atveju funkcija iškviesta kaip
klasės metodas).

    sub naujas {
        my $perduota = shift;
        my $klase = ref($perduota) || $perduota;
        my $mano  = {};
        $mano->{VARDAS}   = undef;
        $mano->{AMZIUS}   = undef;
        $mano->{KOLEGOS}  = [];
        bless ($mano, $klase);
        return $mano;
    } 

Štai ir viskas ką reikia žinoti apie konstruktorius. Jie suteikia
objektams gyvenimą grąžindami nuorodas į supakuotus

nepermatomus daiktus vadinamus objektais. Po to šiuos objektus galima
naudoti iškviečiant jų metodus.

Destruktoriai

viskas kas turi pradžią, turi ir pabaigą. Objekto pradžia yra
konstruktoriaus metodas, o pabaiga –

destruktorius. Destruktorius yra metodas, kuris automatiškai
iškviečiamas tada kai objektas nustoja egzistuoti.

Destruktoriai Perle turi būti pavadinti funkcijos vardu
DESTROY ir naudojami atlikti švarinimo darbus

(uždaryti atidarytas bylas, soketus, ir panašiai)

Kodėl konstruktoriai gali vadintis kaip nori, o detruktoriai ne? Tai
yra būtina todėl, kad konstruktorius iškviečia

pats programuotojas, o destruktoriai yra iškviečiami automatiškai paties
interpretatoriaus (pe rgarbage

collection mechanizmą). Todėl reikia destruktorių vadinti vardu
DESTROY tam kad Perlas žinotų ką

iškviesti. Perlas neduoda garantijų kad DESTROY bus
iškviestas tuoj po objekto sunaikinimo – jis

iškviečiamas kada patogiau pačiam Perlui, todėl destruktoriuje į tai
reikia atsižvelgti.

Kodėl DESTROY rašomas visomis didžiosiomis raidėmis?
Perlas turi tradiciją vadinti visas funkcijas,

kurios bus iškviečiamos pačio interpretatoriaus, o ne programuotojo
vadinti didžiosiomis raidėmis. Panašiai yra su

BEGIN, END, AUTOLOAD bei visais
metodais priklausančiais tie

mechanizmui (žr. perltie dokumentaciją)

Objektinėse kalbose dažniausiai visai nereikia sukti galvos kada bus
iškviestas destruktorius. Jis iškviečiamas tada

kada reikia. Žemo lygio programavimo kalbose, kuriose nėra automatinio
atminties valdymo niekaip neįmanoma padaryti taip,

kad destruktorius būtų iškviestas automatiškai jį sunaikinus – tam
programuotojas pats turi iškviesti desktruktorių

ir atlaisvinti atmintį ir kitus resursus. Perle, ne taip kaip C++,
objektų destruktoriai retai reikalingi, o jei jie ir

reikalingi tai jie iškviečiami automatiškai. Mūsų klasėje
Asmuo mums nereikia destruktoriaus, nes Perlas

pats pasirūpina tokiais paprastais dalykais kaip atminties
atlaisvinimas.

Vienintelė situacija, kai Perlo magija gali nesuveikti gali būti
tokia, kai naudojama duomanų struktūra, rodanti į

pati save:

$sitas-gt;{BETKAS} = $sitas;

Tokiu atveju reikia ištrinti tokią nuorodą į save pačiam, jei
nenorite kad programa naudotų vis daugiau atminties

(memory leak). Tiesa, kai programa baigia darbą, visa atmintis
grąžinama, tad kažkada ji bus

atlaisvinta, išskyrus atvejus kai ji niekada nebaigia darbo.

Perlo objektų pradžiamokslis: pirmoji dalis

Objekto vaizdavimas

Dažniausiai Perle Paskalio įrašas arba C struktūra, arba C+ klasė yra
saugoma anoniminio asociatyvaus masyvo (hešo) pavidalu. Taip
saugoti yra patogu, nes heše galima saugoti neribotą kiekį
elementų, kuriuos galima pasiekti per unikalų hešo raktą.

Jeigu tik norite kažko panašaus į C struktūrą, tai galima daryti
taip:

$irasas = {
    vardas   => "Petras",
    amzius   => 21,
    kolegos  => [ "Juozas", "Nikolajus", "Vaidas"],
};

Jeigu norite lengviau perskaitomo kodo, galite hešo raktus
rašyti didžiosiomis raidėmis:

$irasas = {
    VARDAS   => "Petras",
    AMZIUS   => 21,
    KOLEGOS  => [ "Juozas", "Nikolajus", "Vaidas"],
};

Norėdami prieiti prie vardo „Petras“ galite rašyti
$irasas->{VARDAS}, o norėdami gauti kolegų masyvą galite
rašyti @{ $irasas->{KOLEGOS} }.

Labai panaši idėja yra naudojama ir objektams, tik nereikėtų prieiti
prie objekto sudėtinių dalių prieiti tiesiogiai – tam dažniausiai
yra naudojamos specialiai tam parašytos funkcijos. Galima sakyti kad
objektas turėtų būti tiesiog daiktas, prie kurio duomenų reiktų prieiti
tik per specialias jo funkcijas.

Klasės sąsaja

Tarkim, kad turim klasę Asmuo. Štai kaip būtų galima ja
naudotis:

    use Asmuo;

    $jo = Asmuo->naujas();
    $jo->vardas("Petras");
    $jo->amzius(21);
    $jo->kolegos( "Juozas", "Nikolajus", "Vaidas" );

    push @Visi_asmenys, $jo;  # išsaugom objektą vėlesniam naudojimui

    printf "%s turi %d metus.\n", $jo->vardas, $jo->amzius;
    print "Jo kolegos yra: ", join(", ", $jo->kolegos), "\n";

    printf "Paskutinis asmuo yra %s\n", $Visi_asmenys[-1]->vardas; 

Kaip matote, klasės Asmuo vartotojas nežino (ir neturi
žinoti) kaip yra saugomi duomenys klasėje Asmuo. Visus
duomenis vartotojas pasiekia tik per metodus (t.y. funkcijas, kurios
priklauso klasei)

Konstruktoriai ir objekto metodai

Tačiau kažkas turi žinoti, kaip duomenys saugomi klasėje, ir
tas kažkas yra pati klasė. Klasė aprašo metodus, kuriais
naudojanti galima prieiti prie prie objekto duomenų. Štai kaip galima
aprašyti klasę Asmuo naudojantis standartiniu duomenų
saugojimo hešo nuorodoje būdu. Aprašysime klasės metoda
naujas(), kuris bus objekto konstruktorius, bei tris
objekto metodus vardas(), amzius() ir
kolegos() per kuriuos bus galima prieiti prie objekte
saugomų duomenų.

    package Asmuo;
    use strict;

    ####################################################
    ## objekto konstruktorius (supaprastinta versija) ##
    ####################################################
    sub naujas {
        my $mano  = {};
        $mano->{VARDAS}   = undef;
        $mano->{AMZIUS}    = undef;
        $mano->{KOLEGOS}  = [];
        bless($mano);           # bet zr. zemiau
        return $mano;
    }

    ##############################################
    ## metodai objektu duomenis pasiekti        ##
    ##                                          ##
    ## Metodai nustato reikšmę, jei perduodamas ##
    ## argumentas, ir tik grąžina reikšmę jei   ##
    ## argumentai neperduodami                  ##
    ##############################################

    sub vardas {
        my $mano = shift;
        if (@_) { $mano->{VARDAS} = shift }
        return $mano->{VARDAS};
    }

    sub amzius {
        my $mano = shift;
        if (@_) { $mano->{AMZIUS} = shift }
        return $mano->{AMZIUS};
    }

    sub kolegos {
        my $mano = shift;
        if (@_) { @{ $mano->{KOLEGOS} } = @_ }
        return @{ $mano->{KOLEGOS} };
    }

    1;  # Tam kad 'use' arba 'require' nesikeiktų

Sukūrėme tris metodus, per kuriuos galima prieiti prie objekto duomenų:
vardas(), amzius() ir kolegos().
Jie labai panašūs. Jei nustato reikšmę jeigu iškviečiami su argumentu,
ir grąžina reikšmę jeigu iškviečiami be argumentų.