Perličky (3)

27. 2. 2002
Doba čtení: 6 minut

Sdílet

Po menší přestávce způsobené vánočními svátky a zkouškovým obdobím vám přinášíme další pokračování nepravidelného seriálu o Perlu. Dnes se pokusím shrnout obsáhlé téma o speciálních proměnných a rozsahu platnosti proměnných.

Novinky

Dnešní novinky budeme věnovat takzvaným apokalypsám – článkům, které píše Larry Wall pro internetový magazín perl.com. Jak jsem již napsal, vývoji Perlu značně napomáhají tzv. RFC dokumenty, pomocí kterých může kdokoliv podat návrh či zlepšovák, který je posléze komunitou přijat, nebo odmítnut. Některým zajímavým RFC dokumentům se Larry věnuje právě v apokalypsách.

Návrh, že by Perl 6 měl být poslední verzí, Larry Wall odmítnul a poukázal na to, že je nutné, aby se Perl vyvíjel nadále. Souhlasil s tím, aby se nový Perl choval tiše, ale zároveň se nesmí zapomínat na to, že bude mít pozměněnou syntaxi i sémantiku a každý program bude muset být napsán buď ve staré, nebo v nové verzi. Interpret se na základě nějakého společného znaku rozhodne, jak bude program interpretovat. Larry také souhlasí s tím, že všechny vestavěné funkce v Perlu by měly vracet objekty. Ty se ale budou chovat pro skalární kontext stejně jako „za stara“ a také vnitřní implementace bude pravděpodobně trochu odlehčená. Pokud ale budete chtít s proměnnými pracovat jako s objekty – prosím.

V další apokalypse Larry znovu zopakoval, že by nebylo vhodné implementovat víceřádkové komentáře, a hájí se tradičně tím, že pak jsou kódy plné komentářů, ve kterých se samotný zdrojový kód ztrácí. K tomuto účelu slouží POD. Zárověň ale napsal, že pravděpodobně bude dostupné nastavení pomocí pragma deklarace, které víceřádkové komentáře povolí.

V Perlu 6 budou k dispozici vestavěné objekty INTEGER, NUMBER, STRING, REF, SCALAR, ARRAY, HASH, REGEX a CODE, které se budou chovat jako pravé objekty, a také datové typy int, num, ref atd., které budou k dispozici těm, kdo je nebudou chtít objektově využít (volat na nich metody apod.). Tyto objekty budou vnitřně uloženy úsporněji, což je výhodné, protože pokud si budete chtít alokovat dejme tomu pole čísel, můžete využít právě tyto typy.

Základní speciální proměnné

Pod tímto pojmem mám na mysli všechny speciální proměnné, pole, ovladače vstupu a výstupu a také konstanty. Mezi základní speciální globální proměnné řadím $_, @_ a STDIN/STDOUT. Je nutné si uvědomit, že všechny tyto speciální proměnné, kterými Perl disponuje „přežívají“ v globálním balíku ::main i když jste „zrovna“ v jiném balíku. Tak například:

package abc;
$_ = "HELLO";
package main;
print; # vytiskne 'HELLO'

Výklad o proměnné $_ se ve všech knihách, které jsem měl možnost přečíst, liší. Technicky vzato je to jakási implicitní proměnná pro vstup a vyhledávání vzorů. Míst, kde můžete tuto proměnnou použít, je mnoho, například většina seznamových a unárních funkcí, v iteracích pomocí foreach, ve vstupně/výstupních funkcích či funkcích grep a map nebo v operacích porovnávání (zde se vypouští  ~=).

Uvedu několik příkladů. Pro ty, kteří vidí Perl poprvé, bych nejprve osvětlil „diamantový operátor“ (ovšem není nad vysvětlení od Pavla Satrapy v jeho knize [PPZ] ;-) neboli <>. Tato podivuhodná konstrukce je jednou z možností, jak v Perlu číst z nějakého ovladače (např. ze souboru nebo standardního vstupu STDIN) a vězte, že se používá velmi často, protože Perl byl původně stvořen pro zpracovávání textů. Pokud tedy nebudete nijak nastavovat chování tohoto operátoru, načte jeden řádek z kýženého ovladače (nebo standardního vstupu, pokud ovladač vynecháte). Narazí-li na konec souboru, vrátí undef. Jak prosté. To ale není hlavní téma tohoto odstavce. Tento operátor vrací hodnotu, což je žádané. Vy ale tuto hodnotu nemusíte přiřazovat žádné proměnné. Jak správně tušíte, diamantový operátor uloľí načtený řádek do $_.

while (<>) { print; }
# vytiskne vsechno, co precte na vstupu

while (defined($_ = <STDIN>) { print $_; }
# to samo v blede modre

while (<>) {
    chop;
    next if /root/;
    print $. . $_;
}
# vytiskne vsechny radky, kde se nevyskytuje slovo 'root',
# ze vsech radku pripadne odstrani koncovy znak ENTER
# a navic kazdy radek ocisluje, nyni neco s foreach:

for ("Hrusky", "Jabka", "Svestky") { print; }
# vypise dany seznam na konzoli

Nebudu zde vypisovat, jak se dá implicitní proměnná použít. Můžu vám jen poradit jednu věc. Čtěte perlovské programy, je jich na internetu spousta. Někdy sice zabřednete do otázek typu „Co tohle může dělat???“, ale v drtivé většině se naučíte všechny takové typické konstrukce. Pokud by vás zajímalo, zda konkrétní funkce nebo operátor podporují $_, stačí se podívat do dokumentace.

Implicitním polem se zde nebudeme zabývat. Má své využití zejména u funkcí, kterými se budeme zaobírat později. Co je STDIN/STDOUT, již asi tušíte – ano, standardní vstup resp. výstup. Přesněji řečeno ovladač vstupu a výstupu. Když už jsme u těch ovladačů, zajímavou věcičkou je speciální ovladač DATA. Pokud totiž na konci svého programu (v tomto případě nějakého skriptíku) uvedete speciální globální konstantu __END__, igonruje Perl všechno, co je za touto konstantou. To je celkem logické – vzhledem k významu anglického slova „end“, který všichni určitě znáte. Na co by ale hned tak někdo nepřišel, je to, že všechno, co se nachází za touto ukončovací konstantou, je čitelné pomocí ovladače DATA. Možnost využití této finty již ponechám na vaší fantazii.

Výše uvedený seznam zdaleka není kompletní. Prostudujte dokumentaci vašeho interpretu nebo vezměte jakoukoliv učebnici Perlu (doporučuji [PRP]). Pokud vám vadí poměrně zapeklité značení (které však má něco do sebe a má svou logiku), můžete deklarovat na začátku programu use English;, a každé proměnné bude vytvořen alias s anglickým názvem (tedy např. pro $_ to bude $ARG – což je však pro ortodoxního Perlistu nepřijatelné, ten se totiž většinou drží hesla: „čím míň, tím líp“).

Můj, tvůj, náš, váš…

Perl podporuje jak dynamický, tak lexikální rozsah platnosti, což je poněkud pozoruhodné. Jako příklad dynamického rozsahu platnosti bych mohl uvést např. jazyk Lisp. V dynamickém rozsahu platnosti se hledaná hodnota proměnné nehledá v aktuálním prostředí, ale v prostředí nadřazeném. Pomocí modifikátoru local můžete určité globální proměnné „zapůjčit“ na určitou dobu tuto vlastnost. Proměnná tak překryje globální hodnotu a stane se jaksi „nezávislou“ na překryté globální proměnné. Po určité době (resp. ukončení bloku) se do takto deklarované proměnné vrátí hodnota globální proměnné, která byla překryta.

Háček je v tom, že takováto „lokální“ proměnná se dá změnit i „zvenku“. Pokud např. zavoláte funkci, která se bude snažit modifikovat překrytou globální proměnnou, podaří se jí to a skutečně modifikuje novou proměnnou, deklarovanou pomocí local. Na konci bloku se sice navrátí původní hodnota, ale to už může být pozdě. Proto se tento způsob až na výjimky nedoporučuje používat. Perl nabízí jiné řešení.

Modifikátor my překryje proměnnou z nadřazeného prostředí tak, že se nová takto deklarovaná proměnná již nedá odjinud modifikovat. Tímto způsobem vám doporučuji vytvářet lokální proměnné. Při psaní programů v Perlu se držíme, ostatně jako ve všech imperativních programovacích jazycích, hesla „Čím méně globálních proměnných, tím lépe“!

my ($a, $b) = (1, 2);

Nebyl by to Perl, aby pro vás neměl schováno ještě něco navíc. Pokud přece jenom budete muset použít globální proměnnou, použijte k tomu our. Our dělá přesně to, co my, jenže řekněme – opačně. Proměnná deklarovaná tímto způsobem je od té chvíle brána jako globální. Můžete ji beztresně používat, měnit, jak je libo. Jenom je nutné si uvědomit, že vícenásobným „zanořením“ pomocí our se hodnota již zpět nevrátí. Pokaždé, ať už jste jakkoliv „hluboko“ (myšleno v prostředí), budete nastavovat stejnou proměnnou.

bitcoin_skoleni

$x = "global";

sub f {
    our($x) = "taky global";
    $x .= ", ale odjinud";
}

Na závěr bych rád připomenul, že v Perlu jde jedna věc udělat tisícero způsoby. Nebombardujte mě prosím maily typu „takhle to jde lépe“. Je mi jasné, že bruslím na tenkém ledě. Je nutné si uvědomit, že každý programátor v Perlu musí mít svůj styl. Každý se Perl naučil jinak. Rád si však přečtu vaše připomínky a komentáře v diskusích pod články – nerad bych totiž plodil bludy, což se zejména v případě Perlu může stát. Při této příležitosti bych také poprosil všechny, kdo znají nějaký hezký perlovský „oneliner“ typu „vypiš prvních n prvočísel“, aby mi ho hodili na mail. V příštím díle bych chtěl několik odstavců věnovat právě jim.

Použitá literatura:
[PLD] Kolektiv autorů: Perl documentation, distribuce Perlu
[PPZ] P. Satrapa: Perl pro zelenáče Neokortex, ISBN 80–86330–02–8
[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

Seriál: Perličky