Perličky (2)

6. 12. 2001
Doba čtení: 8 minut

Sdílet

V dnešním dílu se budeme nadále věnovat skalárům, polím a hashům. Pomocí odkazů budeme vytvářet různé zapletence a něco si povíme o kontextech, pravdivostních hodnotách a konstantách. Samozřejmě, že se v úvodu článku dozvíme nějaké ty novinky a také se budeme věnovat návrhu Perlu 6.

Novinky

Dnes začneme konečně nějakými novinkami. V Pondělí 19. 11. 2001 se uskutečnil v Praze v jedné nejmenované hospůdce první sraz Prague Perl Mongers. Perl Mongers jsou zájmové skupiny programátorů v Perlu, které jsou v mnoha zemích. Lidé, kteří Perl používají, se scházejí, diskutují a navzájem si pomáhají. Osobně jsem se setkání bohužel neučastnil, ale do Prahy se vydal můj kolega, který mě s probíranými tématy obeznámil. Sešlo se všehovšudy pět lidí, ale za večer se několik jedinců prostřídalo.

Koncem prázdnin 2000 hlavní vývojáři Perlu poprvé vypustili informaci o Perlu 6. Že se něco musí dělat, bylo jasné už delší dobu, protože Perl 5 má určité problémy, o kterých jsem psal v minulých Perličkách. Oni však poprvé sdělili komunitě základní myšlenky, kterými Perl 6 půjde. Pokusím se je na následujících řádcích shrnout a příště se budeme věnovat současnému dění okolo návrhu šestky.

Perl 6 bude úplně přepsán. Je nutné zbavit se všech neduhů, které se táhnou od prvních verzí. Bude kompletně předělána vnitřní struktura, přičemž bude použito nejmodernějších technologií analýzy. Co však ještě nebylo rozhodnuto, je jazyk, ve kterém bude Perl napsán. Žhavými kandidáty jsou C a C++, přičemž o C se mluví jako o favoritovi (zejména u jádra).

Každopádně díky zcela novému návrhu bude také konektivita na ostatní jazyky jednodušší. V Perlu 5 funguje systém XS, pomocí kterého můžete z Perlu volat funkce jazyka C. Všechno ale v XS není zcela průhledné, záludnosti čekají na každém řádku. Počítáno je také s vlákny, přenositelností, již výše zmíněnou rozšiřitelností, flexibilitou a také rychlostí. Vývojáři rozhodně nechtějí udělat něco, co by se v rychlosti mohlo porovnávat s Javou.

Celý Perl 6 byl rozdělen do několika hlavních částí. Tou první je parser, který se musí vypořádat ze zadaným zdrojovým kódem a proměnit ho ve strom syntaxe. Parser bude pravděpodobně (jako všechny ostatní části) samostatný modul. Díky tomu může Perl 6 podporovat různá paradigmata. Chcete programovat v syntaxi podobné jazyku Scheme? Můžete! Je libo Ruby, Tcl či C#? Stačí zvolit ten správný modul. Samozřejmě, že hlavním modulem bude jazyk Perl. Tato distribuce s sebou přináší další výhody.

Strom syntaxe se v druhém kroku předá kompilátoru. Kompilátor jej překóduje do bytekódu, provede elementární optimalizace a předá jej optimizátoru. Ten bude již některým částem kódu „rozumět“ a bude provádět různé optimalizace či JIT předkompilace. Posledním článkem je interpret, který může daný kód přímo vykonat, uložit do souboru, přeložit do jiného formátu (Java, .NET) nebo transformovat do strojového kódu cílové platformy. Interpret bude samozřejmě virtuální počítač a bude provádět vlastní instrukce. Vývojáři si slibují právě od interpretu nejvyšší sílu. Měl by být díky současným poznatkům rychlý, efektivní, měl by umět operovat v 64bitech, bude mít přerušení, bude rozumět regulárním výrazům, zkrátka a dobře by to měl být vysoce výkonný virtuální počítač vyladěný na současné požadavky.

Perl 6 by měl tedy být nejvíce rozšiřitelný jazyk, který kdy byl vytvořen. Můžeme k němu přistupovat jako k jazyku vyššího stupně či jako k systémovému jazyku. Samozřejmě, že současný trend natlačil celý návrh do objektového prostředí, což znamená, že se Perl bude chovat celý objektově, protože to bude pravděpodobně nejsilnější přístup. Stále ale bude možno vytvořit jednoduchý neobjektový program či programovat v jakési směsi paradigmat – což je výhodné. Součástí jazyka bude samozřejmě silná knihovna funkcí pro základní operace vč. moderních přístupů, jako jsou XML, Unicode, vlákna a podobně.

"What do people think?
What, do people think? – L. Wall 

Kontext je v Perlu důležitý

Ještě než se vrhneme střemhlav na různé fígle a vychytávky s poli a hashi, řekneme si něco o kontextech. A předtím, než vám ukážu kontexty Perlu, podíváme se na to, co je to vlastně seznam, protože ten je pro programátora v Perlu denním chlebem.

Seznam je množina prvků. Seznam musíme v Perlu chápat jako něco základního, protože seznam se nepoužívá pouze pro skaláry, jak uvidíme později. Seznam může stát napravo i nalevo přiřazovacího příkazu a dá se indexovat. Prvky seznamu se píší do kulatých závorek a oddělují se čárkami.

();         # prázdný seznam
(0);        # jednoprvkový seznam
(1, 2, 3);  # tříprvkový seznam

# následující konstrukce je naprosto korektní a běžná
($a, $b, $c) = ('A', 'B', 'C');

# jak jsem řekl, seznam se dá indexovat (začíná logicky od nuly)
$typ_vozu = ("Škoda", "Trabant", "Rover")[2];

# vytiskne tu nejdražší anglickou značku
print $typ_vozu;

# seznamy se používají zejména k naplnění polí a hashů
@pole = (1, 2, 3);
%hash = ("klíč 1", 1, "klíč 2", 2);

# ano, i hash se dá inicializovat pomocí seznamu a ve skutečnosti to tak
# Perl dělá. speciální znak "=>" je pouze náhražkou za čárku, kterou
# si tam Perl potom stejně dá (ono to vypadá o mnoho lépe)
%hash = ("klíč 1" => 1, "klíč 2" => 2);

# otázkou zůstává, co bude interpret říkat na to, když se pokusíme hash
# inicializovat lichým počtem prvků:
%hash = ("k_1", 1, "k_2");

# zkuste to! nebude z toho moc nadšen, něco zabrumlá, ale program
# fungovat bude (poslední prvek se zkrátka vyšoupne z kola ven)

Seznamy se ale nedají do sebe vnořovat. Jakmile Perl narazí na vnořený seznam, urychleně jej rozvine, tzn. „odstraní závorky“.

$pocet = @dvojice = (
  ("Lukáš", "Petra"),
  ("Tomáš", "Magda"),
  ("Marek", "Břetislav"),
);

# pole @dvojice nyní obsahuje šest řetězců
# (nikoliv tři seznamy o dvou prvcích)
# skalár $pocet obsahuje počet prvků v poli

print $pocet; # vytiskne skutečně 6 (a ne 3)

V Perlu rozeznáváme dva kontexty: skalární a seznamový. Kontext lze chápat jako okolí, ve kterém daný výraz stojí. V zásadě by se to dalo ilustrovat následovně:

("nyní jsem v seznamovém kontextu", "tady také",
"zkrátka v seznamu");

1;

# všechno, co není v seznamu, je v kontextu skalárním
# jednička o tři řádky výše je tedy ve skalarním kontextu

Skalár samozřejmě vrací vždy svou hodnotu, Pole ve skalárním kontextu vrací počet prvků a v seznamovém všechny své prvky. No a konečně hash vrací ve skalárním kontextu interní hodnotu Perlu, a to počet alokovaných buňek pro hodnoty a jejich využití (tuto informaci pravděpodobně nikdy potřebovat nebudete), a v seznamovém kontextu vrací své prvky a klíče pěkně za sebou, což také asi málokdy využijete. Jako nejzajímavější věc se mi jeví pole ve skalárním kontextu, což má použití například:
for ($i=0; $i < @pole; $i++).

Opravdová bomba je, že funkce mohou vracet také seznamy (a ony to také většinou dělají). Perl je vybaven klíčovým slovem wantarray. Funkce si tak může zjistit, zda má vracet seznam, nebo skalár.

# funkce vrací dva kořeny kvadratické rovnice
($x1, $x2) = quadratic_equotion(16, 0, -4);

# učebnicovým příkladem je funkce split, která rozdělí řetězec dle
# zadaného regulárního výrazu, který je dělitelem řetězce

# rozdělím řádek na slova a výsledný seznam uložím přímo do pole
@words = split /\s/, $line;
# /\s/ je regulární výraz zastupující bílé znaky (mezera, tabelátor...)

# chci-li vytisknout poslední číslo dané IP adresy
$ip = "192.168.192.168";
print( (split /\./, $ip)[3] );

# zkuste si to!

Tabulka č. 217
ZKUSTE SI TO!

Do následujících proměnných uložte hodinu, minutu a sekundu daného času: $hod pro hodiny, $min pro minuty, $sec pro sekundy. Použijte funkci split (parametry nedávejte do závorek – v Perlu to není nutné) a seznam. Napovím, že znak „:“ nemá v regulárních výrazech žádný speciální význam. Nezapomeňte na středník na konci výrazu!

$time = "14:22:55";

Konstanty a typegloby

Programátor v Perlu konstanty kupodivu většinou nepotřebuje. Díky hashům a jistým zažitým konvencím, jako jsou konfigurační soubory, a samozřejmé přirozenosti zpracování textů člověk sáhne po konstantách až v krajním případě. Můžete to v zásadě udělat těmito způsoby:

nejpřirozenější je vytvořit si funkci,
která prostě vrátí hodnotu
sub PI { 3.1415 };

# uvedený způsob má ale jednu nevýhodu:
# v jiném kontextu byste museli funkci
# volat explicitně, ale nebojte se, Perl
# má řešení:

use constant PI => 3.1415;

což si Perl převede na

*PI = sub { 3.1415 };

Hodnota *PI je typeglob, což je speciální typ, který jsem vám zatajil. Hvězdička zde reprezenuje jakýsi zástupný znak, protože typegloby modifikují hodnoty přímo v tabulkách proměnných Perlu. Byly potřebné, ještě když Perl neuměl odkazy, ale dnes se používají zřídka. Jejich využití je právě u odkazů nebo u ovladače souboru. Například pokud byste si chtěli ve skaláru uchovat ovladač souboru, museli byste to udělat následovně:

open F, "t.pl"
$f = *F;
close $f;

Pravdivostní hodnoty

Kdo vidí Perl poprvé, může se divit, kde že se nám ztratil oblíbený boolean. Predikáty v Perlu také vracejí pravdivostní hodnoty. Perl pro ně nezavádí žádné speciální proměnné, ale využívá obyčejný skalár (ve skalárním kontextu – neexistuje tedy žádný speciální pravdivostní kontext). Zapamatujte si pouze následující větu, kterou naleznete téměř ve všech učebnicích a přírůčkách: „Nepravda je nula (včetně řetězce "0“), prázdný řetězec, undef a všechno ostatní je pravda." Pozor na ten řetězec „0“ – to je také nepravda. Můžete tak nevědomky zanést do programu chybu, kdy uživatel (nebo třeba jméno souboru) bude zrovna „0“ (samozřejmě, že to se stane, pokud předáváte systém zákazníkovi – Murphyho zákon). Perloví zelenáči by nyní měli zbystřit pozornost. Sledujte následující funkci (vymýšlet smysluplné demonstrační příklady není tak snadné, jak jsem si zprvu myslel).

sub connect {
    $username = shift;
    $password = shift;

    return if not Datastore_Connect($username, $password);
    print "Connected...\n";
    return 1;
}

Všiměte si návratové hodnoty v první podmínce. Ona tam vlastně žádná není. To není překlep, protože funkce return volaná bez parametrů implicitně vrací nepravdu. Mohli byste tedy napsat „return 0;“ – je to to samé v bledě modrém. Ušetříte tak dva bajty. Pro neznalé: o funkcích si povíme později.

Jak to tak vypadá, k fintám s poli a hlavně s hashi, na které se tak těším, jsem se opět nedostal. Moc jsem se zkrátka rozepsal o Perlu 6. Takže příště.

Odkazy:

Perl Mongers Homepage
Perl.com

bitcoin_skoleni

Použitá literatura:

[PLD] Kolektiv autorů: Perl documentation, distribuce Perlu
[PRP] L. Wall, T. Christiansen, J. Orwant: Programming Perl, 3rd edition, O`Reilly, ISBN 0–596–00027–8
[EPP] J. N. Hall, R. L. Schwartz: Effective Perl Programming, Addison-Wesley, ISBN 0–201–71975
[PCB] T. Christiansen, N. Torkington: Perl Cookbook, O`Reilly, ISBN 1–56592–243–3
 

Seriál: Perličky