Perl 5.22.0 a vše okolo

Včera večer byla uvolněna jako každý rok na přelomu května a června nová verze perlu 5. Co se za poslední rok změnilo?

2.6.2015 08:00 | Jiří Václavík | přečteno 19624×

Perl 5 pokračuje, možná trochu ve stínu perlu 6, jehož interpret v první stabilní verzi by snad již letos opravdu měl vyjít, poklidně ve vývoji. Cílem dnešního článku je postupně projít některé změny, které se za poslední rok od verzí řady 5.20 udály a trochu čtenáře zasvětit do toho, co se s perlem vlastně v poslední době děje.

Na začátku je třeba podotknout, že vývoj perlu 5 běží nezávisle na perlu 6, ačkoliv jsou velmi často změny v perlu 5 perlem 6 inspirovány. Jde ale o dva různé jazyky a dva různé týmy lidí, kteří se na jejich vývoji podílejí.

Hlavním člověkem a release managerem posledních major verzí je již od řady 5.16 Ricardo Signes.

Instalace

Na distribuční balíčky nové verze perlu si asi budeme muset chvíli počkat, ale kdo by chtěl, může si novou verzi nainstalovat ze zdrojových kódů.

Doporučit lze instalaci pomocí nástroje perlbrew, který je přímo určen pro správu několika verzí perlu zároveň a nevyžaduje žádné zásahy do stávajícího systému, takže nový perl může testovat opravdu každý. Navíc pomocí něj lze instalovat také vývojové verze, release candidate distribuce atd.

Instalace perlbrew je velmi přímočará. Postupujme pomocí návodu na perlbrew.pl. Příkaz

> wget -O - http://install.perlbrew.pl | bash

provede instalaci samotného perlbrew. Pro instalaci konkrétní verze perlu do perlbrew pak zavoláme

> perlbrew install perl-5.22.0

Dále můžeme zvolit implicitní verzi perlu pro stávající sezení

> perlbrew switch perl-5.22.0

a nebo místo toho volat všechny příkazy s prefixem

> perlbrew exec --with perl-5.22.0 [příkaz]

Tedy například:

> perlbrew exec --with perl-5.22.0 perl program.pl arg1 arg2

My budeme dále v tomto článku používat alias perl5.22.0:

> alias perl5.22.0="perlbrew exec --with perl-5.22.0 perl"

Verzování perlu

V posledních letech se ustálila linuxovým jádrem inspirovaná pravidla pro vydávání nových verzí perlu 5:

Změny oproti řadě 5.20

Pojďme se tedy podívat na konkrétní změny. Zde jsou vybrány pouze některé, pokud možno ty zajímavější. Kompletní přehled je v dokumentu perldelta, který je součástí distribuce. Dokument perldelta má zčásti formální syntaxi a existují nástroje, díky kterým dostaneme rozdíl mezi libovolnými verzemi perlu. Je tedy v podstatě sám o sobě jednoduchým správcem verzí.

Operátor vstupu <<>>

Operátor <> se používal jako zkratka pro <ARGV>, kde ARGV byl implicitně definovaný ovladač souborů předaných na příkazovém řádku, pokud byly definované; nebo případně vstup z STDIN. Díky této konstrukci lze v perlu velmi snadno předané soubory číst.

Tento způsob čtení pomocí operátoru <> má ovšem jeden nedostatek - nelze ho použít pro všechny soubory. Ve skutečnosti se totiž argumenty příkazového řádku ještě interpretují, což v některých okrajových případech může způsobit pro někoho možná nečekané chování. Příklady interpretovaných znaků je |, >, >> apod.

Pojďme se podívat podrobněji o co jde. Nejprve vytvořme soubor s trochu obskurním jménem echo SOUCAST_JMENA_SOUBORU | a uložme do něj nějaký obsah.

> echo 'OBSAH SOUBORU' > 'echo SOUCAST_JMENA_SOUBORU |'

Nyní je již jasné, kam míříme. Zkusme nyní číst pomocí operátorů <> a <<>> a pozorujme rozdíl:

> perl5.22.0 -e 'while (<>) {print;}' 'echo SOUCAST_JMENA_SOUBORU |'
SOUCAST_JMENA_SOUBORU
> perl5.22.0 -e 'while (<<>>) {print;}' 'echo SOUCAST_JMENA_SOUBORU |'
OBSAH SOUBORU
>

V prvním případě došlo k interpretaci argumentu, zatímco v druhém se nic takového nestalo.

Zájemci si mohou zkusit totéž se souborem začínajícím na > a smazat tak obsah potenciálně existujícího souboru.

Otázkou je, jak řešit tento problém v dřívejších verzích perlu. K pochopení by mohla napomoci souvislost s funkcí open. Z podobného důvodu totiž kdysi došlo ke vzniku tříparametrové varianty této funkce, kdy se odděluje mód a název souboru. Jak byste například u dvouparametrové varianty četli soubor začínající na >? U open je problém ještě zřejmější, protože se tam speciální znaky (narozdíl od jejich výskytu u jmen souborů) běžné používají. Proto ostatně změna u open nastala již u verze 5.6. Ale zpět k řešení problému u <> - pomoci by nám zde měla právě tříparametrová funkce open. Ta v podstatě přesně vystihuje rozdíl mezi <> a <<>>. Následující kód s tříparametrovou funkcí open hezky popisuje změnu <<>> oproti <>:

FILE:
for my $file (@ARGV) {
    open my $fh, '<', $file || next FILE;
    while(my $line = <$fh>){
        print $line;
    }
}

Jak je to s experimentálními featurami

Je-li nějaká funkcionalita experimentální, pak to jednoduše znamená to, že bychom měli být obezřetní, neboť se její chování může změnit. Experimentální featury podle interních pravidel vydávání musí zůstat nezměněny alespoň 2 roky (nepočítají se samozřejmě změny v dokumentaci, refactoring kódu, znění chybových hlášek atd.). Po této lhůtě lze diskutovat o zrušení příznaku "experimentální".

I když víme, že se chování nezmění (tj. hlavně proto. že používáme starou verzi perlu a v nové již featura experimentální není), musíme to reflektovat v kódu. Jednotlivé featury mají svá jména a před použitím bychom měli zavolat pragmu feature:

use feature qw(featura);

Takto ovšem použití dané featury nadále generuje varování. Chceme-li ho umlčet, přidáme ještě tento řádek:

no warnings 'experimental::featura';

Je ovšem na důkladné zvážení, zda se používání jakékoliv experimentální featury vyplatí a nestojí za to počkat si dva roky až bude syntaxe stabilní. Pokud jde daný problém vyřešit jinak a není s tímto řešením jiný problém, pak bychom se pro něj měli rozhodnout, protože takové řešení je čistější.

Příkladem experimentální featury jsou od řady 5.20 signatury v definicích podprogramů místo používání proměnné @_.

Vytváření aliasů přiřazením do reference

Aliasem myslíme proměnnou, která ukazuje na stejné místo v paměti jako nějaká jiná proměnná.

Aliasing je experimentální featura, takže platí vše z předchozího odstavce. Přibližme si o co v případě aliasingu půjde. Jelikož experimentální featury je třeba zapnout, zadejme

use feature qw(refaliasing);
# no warnings 'experimental::refaliasing';

Je možná následující syntaxe pro vytvoření aliasu proměnné, například:

\%new_hash = \%old_hash;
is(\%new_hash, \%old_hash, "oba hashe ukazují na stejné místo v paměti");

\&new_code = \&old_code;
is(\&new_code, \&old_code, "oba podprogramy jsou též aliasy");

Díky této vlastnosti je možné při procházení složitější datové struktury získat přímo pole místo pouhého odkazu na něj. Konkrétně tedy místo

for my $hashref (@list_of_hashes) {
    process(%$hashref);
}

můžeme napsat o něco expresivnější

for \my %hash (@list_of_hashes) {
    process(%hash);
}

Detailnější možnosti jsou v dokumentu perldelta.

Unicode

Nový perl přichází s podporou aktuální verze Unicode 7.0.

Regulární výrazy

Asi nejzajímavější nová věc je, že máme k dispozici rozšířenou syntaxi pro boundaries. \b standardně znamená kotvu pro hranici slova. Je trochu ošemetné mít v jazyce něco závislého na slově, protože sama definice slova je velmi nejasná a napříč jazyky se může diametrálně lišit. Totéž platí o větách, jejichž koncept navíc v mluveném jazyce zcela ztrácí smysl. Přesto jsou boundaries pro jednoduché tokenizátory poměrně dobře funkční. Lingvistům nyní udělají velkou radost následující nové kotvy:

Rozdíly si můžeme krátce demonstrovat. Představme si, že máme následující tokenizery:

my $tokenizers = {
    b   => qr{(?:\b)}xms,
    sb  => qr{(?:\b{sb})}xms,
    wb  => qr{(?:\b{wb})}xms,
    gcb => qr{(?:\b{gcb})}xms,
};

Budeme chtít zobrazit, kde jsou boundaries v nějakém textu:

my $text = "Aaaa a aaaa aaaaa aa. B. Cc'c ccc'ccc c\"c. D\x{307}d\x{307}.";

for my $boundary_type (keys %$tokenizers) {
    my $text_copy = $text;
    $text_copy =~ s{$tokenizers->{$boundary_type}}{|}xmsg;
    print "$boundary_type: $text_copy\n";
}

Z výsledku je pěkně vidět, jak jednotlivé boundaries fungují:

b:   |Aaaa| |a| |aaaa| |aaaaa| |aa|. |B|. |Cc|'|c| |ccc|'|ccc| |c|"|c|. |Ḋḋ|.
wb:  |Aaaa| |a| |aaaa| |aaaaa| |aa|.| |B|.| |Cc'c| |ccc'ccc| |c|"|c|.| |Ḋḋ|.|
sb:  |Aaaa a aaaa aaaaa aa. |B. |Cc'c ccc'ccc c"c. |Ḋḋ.|
gcb: |A|a|a|a| |a| |a|a|a|a| |a|a|a|a|a| |a|a|.| |B|.| |C|c|'|c| |c|c|c|'|c|c|c| |c|"|c|.| |Ḋ|ḋ|.|

Už jen stručně další změny v regulárních výrazech:

Mazání deprecated featur

Jedním z hlavních důvodů, proč by se nové featury měly přidávat do jazyka jen velmi opatrně po dlouhé diskuzi je nutnost zpětné kompatibility, na kterou se v perlu velmi striktně dbá. Jakmile se totiž do široce používaného jazyka zavede funkcionalita, která není žádoucí (např. z důvodu matoucí interpretace, narušení jiných a třeba i budoucích a zatím neplánovaných featur), je to obrovský problém, protože cesta zpátky je téměř nemožná. Čištění jazyka nicméně v omezené míře probíhá, i když nějaké zásadní změny se z výše uvedeného důvodu dít nemohou. (Od toho bude perl 6.)

Podle Richarda Signese bude v jazyce každá funkcionalita označená jako deprecated minimálně další dva roky (výjimečně i pouze rok, ale to se ještě nestalo) a bude generovat varování. Potom může (a taky nemusí) dojít jejímu odstranění. Několik deprecated syntaktických konstrukcí (některé byly deprecated i 20 let) bylo nyní odstraněno:

Obecně lze říci, že cokoliv deprecated nemá vůbec žádný smysl používat, protože to může být v budoucnu odstraněno. Navíc je stejně velmi pravděpodobné, že takováto featura bude v silném rozporu s Perl Best Practices, jejichž striktní používání je v moderním perlu naprosto nezbytné.

Odstraněná funkcionalita

Podívejme se jen pro zajímavost a ilustraci, co v perlu vlastně bylo, na několik featur, které jsou nově odstraněny. Všimněme si mimochodem, jak dramaticky všechny následující kostrukce snižovaly čitelnost kódu.

Změny specifické pro platformy

Verze pro Windows podporuje konstrukce s rourou u tříparametrové funkce open, což doposud možné nebylo:

open my $fh, '-|', @list;
open my $fh, '|-', @list;

Změny v modulech

Odstraněn z core modulů byl kdysi nepostradatelný modul CGI. V době MVC a jiných frameworků a šablonovacích systémů již není třeba. Dále byl odstraněn modul Module::Build z důvodu nepohodlných závislostí (automake).

Všechny bývalé core moduly jsou samozřejmě nadále na CPANu.

Další změny stručně

Další zdroje informací


Článek je vydán bez honoráře.
Online verze článku: http://www.linuxsoft.cz/article.php?id_article=2005