LINUXSOFT.cz Přeskoč levou lištu
Uživatel: Heslo:  
   CZUKPL

> Perl (146) - Perl 6 - jazyk budoucnosti

Perl Na Perl 6 jsme čekali již před začátkem tohoto seriálu. Stále čekáme. Ale bude stát za to.

15.11.2011 00:00 | Jiří Václavík | Články autora | přečteno 5167×

Perl 6 je rodící se skriptovací jazyk, který vzniká na základě Perlu 5. Bude dalším stupněm nejen ve vývoji Perlu, ale půjde o velký krok v evoluci programovacích jazyků obecně. Jeho hlavními filozofiemi jsou hesla "make easy things easier" a "keep Perl 6 Perl".

Vznik

Původním cílem bylo odstranit některé nešvary z Perlu 5. Larry Wall ve své přednášce na Perl Conference prohlásil: "Easy things should stay easy, hard things should get easier, and impossible things should get hard".

Základní myšlenky Perlu 6 byly na této konferenci tedy položeny již v červenci roku 2000. Následovala veřejná diskuze ve formě několika RFC (request for comments).

Poté Larry Wall napsal několik článků (zvaných Apokalypsy), kde představil, které změny by měl Perl 6 obsahovat, které ne a které možná. Číslování Apokalyps je shodné s číslováním kapitol v knize Programming Perl. V každé Apokalypse je tedy popsáno, co by se mělo z dané kapitoly změnit.

Z Apokalyps poté vznikly vychytáním sporů mezi jednotlivými Apokalypsami Synopses, ze kterých vychází specifikace jazyka. To je zásadní rozdíl oproti Perlu 5. V Perlu 5 specifikace neexistovala a museli jsme se spokojit s popisem chování (fakticky byla tedy specifikace dána zdrojovými kódy interpretu Perlu 5 a dokumentace byla pouze jejich popisem). Nyní je v Synopses jasně deklarováno, jak by se Perl měl chovat a podle nich bude interpret fungovat. Pokud se tedy bude lišit specifikace a chování interpretu Perlu 6, bude třeba interpret opravit.

Také existuje série tzv. Exegesis, což jsou výklady Apokalyps (na příkladech je zde vysvětleno nové chování).

Interprety Perlu 6

Zásadní změnou oproti Perlu 5 bude to, že nově bude moci existovat více implementací interpretu jazyka.

Existuje několik projektů, které vyvíjejí interpret Perlu 6, avšak žádný ještě nedospěl do svého konce. Již mnohokrát bylo anoncováno datum, kdy Perl 6 spatří světlo světa, ale zatím nabírá stále nová zpoždění. Od jisté doby se manažeři projektu vyjadřují slovy "Perl 6 has no schedule".

Již nyní můžeme pomocí těchto projektů zkoušet syntaxi Perlu 6. Stačí, když si stáhneme nějaký z nabídky aktuálně vyvíjených interpretů. Jednou z možností je instalace Rakudo Perlu, po které nám vznikne spustitelný soubor perl6. Nakopírujme ho do některého z adresářů v proměnné prostředí $PATH. Nyní můžeme spouštět naše programy v interpretu perl6 (je třeba si uvědomit, že řada věcí je zde ještě neimplementovaných).

$ perl6 -v
This is Rakudo Perl 6, version 2010.11 built on parrot 2.10.1Null PMC access in get_bool()
current instr.: 'perl6;Perl6;Compiler;version' pc 326465 (src/gen/perl6-grammar.pir:16967)
called from Sub 'perl6;PCT;HLLCompiler;command_line' pc 1855
(compilers/pct/src/PCT/HLLCompiler.pir:917)
called from Sub 'perl6;Perl6;Compiler;main' pc 326404 (src/gen/perl6-grammar.pir:16945)
$ perl6 hello_world.pl6

Také lze spustit perl6 bez argumentu. Objeví se perl6 shell, který se hodí pro naše další pokusy.

$ perl6
> note 123
123
>

Vztah Perl 6 s předchozími verzemi

Perl 6 nebude s předchozími verzemi zpětně kompatibilní. To znamená, že zdrojový kód programu napsaného v Perlu 5 nemusí fungovat (nebo může fungovat jinak). Důležité však je, že archiv CPAN bude i v Perlu 6 nadále k dispozici, neboť bude možné používat Perl 6 ve speciálním módu, kde kompatibilita bude.

Změny oproti Perlu 5

Již bylo řečeno, že asi nejzlomovějším rozdílem je existence specifikace. Na základě ní tedy lze kdykoliv vytvořit interpret jazyka. Avšak kdyby šlo jen o ni, tak by se z praktického hlediska v Perlu 6 nic nezměnilo. Věnujme se tedy dále změnám v syntaxi jazyka. Změn je obrovské množství. Máme řadu nových funkcí, operátorů (ačkoliv "Operators are just functions with funny names and syntax"), konstrukcí a změn v syntaxi. Zde si představíme jen ty nejviditelnější změny. Následující text by měl sloužit zejména pro orientaci, co je v Perlu 6 možné, nikoliv jako komplexní příručka. Ta by totiž vydala na desítky dílů.

Koho zajímá více, než jen letmý pohled, měl by se podívat do specifikace jazyka, kde najde skutečně všechno.

Použití kódu Perlu 5

I v Perlu 6 budeme moci používat nespecifikvaný kód Perlu 5.

use v5;
{
    # Perl 5 kód
}
use v6;
{
    # Perl 6 kód
}

Výpis textu

Existuje příkaz say jako alternativa print, která navíc vytiskne znak nového řádku.

say "Hello world";

Sigil se nemění pro získání prvku pole

Sigil (znak, který označuje začátek proměnné) zůstává v Perlu 6 stejný i po operaci "prvek pole" nebo "prvek hashe".

Konkrétněji, následující příklad bude běžným zápisem (v Perlu 5 bychom měli změnit u @pole[2] zavináč na dolar).

my @pole = (1 .. 10);
my $treti_element = @pole[2];

Twigils

Také se objevují tzv. twigils. To jsou proměnné se dvěma sigil znaky. Vyskytují se následující twigils:

TwigilVýznam
. přístup k datům objektu, veřejná data
! přístup k datům objektu, soukromá data
? pro data známé v době kompilace; například $?LINE místo starého __LINE__
* například $*IN, $*OUT, $*ENV, $*PID, $*ARGV
^ proměnná jako poziční parametr, používá se i například jako $^a, $^b, $^c atd. (řazené lexikograficky) místo starých $a a $b
:pojmenovaný parametr
< $<zachyceni> zachytávání zapamatovaných hodnot u regulárních výrazů; využijeme v příštím dílu
=POD proměnná
~subjazyky (například $~MAIN, $~Q, $~P5Regex)

Deklarátory

Podívejme se, jakými způsoby lze deklarovat proměnné.

DeklarátorVýznam
mylexikálně vymezené proměnné
statelexikálně vymezené perzistentní proměnné
ourbalíkové proměnné
hasatributy objektů
anonanonymní jména
augmentpřidává definice (například regulární výraz do gramatiky, uvidíme v příštím dílu)
supersedemění existující definice

Končí local, ale lze používat temp.

Méně závorek

U často používaných konstrukcí mohou být vynechávány kulaté závorky. Cykly a podmínky tak lze psát v tomto stylu (dříve to bylo možné pouze v postfixovém zápisu).

if 5 < 10 {
    say "OK";
}

Definice pole

Podobně je to s definicí pole. Operátor čárka se zde již chová jinak (v Perlu 5 by následující kód měl úplně jiný význam - toto lze uvést jako důkaz nekompatibility Perlu 6 s předchozími verzemi).

@pole = 1, 2, 3;

Pro vytváření pole řetězců nyní máme místo qw novou syntaxi.

@retezce = <a b c>

Nově lze snadno na pole konvertovat proměnnou s mezerami.

@retezce = <<a $prvky_oddelene_mezerou c>>

Exsituje také speciální operátor Q pro uvozování, který přijímá různé modifikátory.

Líné vyhodnocování

Lze vytvořit pole s "nekonečně mnoha" prvky uvedením hvězdičky nebo Inf jako horní meze. Následující kód bude fungovat.

my @pole = 0 .. Inf;
say @pole[10000];

Obsah pole se vyhodnocuje líně. Dokud ho nepotřebujeme, nebude se počítat. Příslušná část se vyhodnocuje, jakmile je to potřeba (čtení hodnoty).

S tím souvisí i zavedení konstrukce gather...take. Vytvoříme pole @nadruhou všech čtvercových čísel od 0 do nekonečna.

@nadruhou = gather for 0 .. Inf {
    take $_ ** 2;
};

Celý proces se zde vyhodnocuje líně, což znamená, že příslušné hodnoty prvků pole @nadruhou budou dopočteny teprve až dojde k jejich přečtení. Díky tomu není plýtváno cennými jednotkami CPU, pokud výpočet nebude potřeba.

Hybridní typový systém

V Perlu 5 jsme se vůbec nemuseli starat o datové typy používaných proměnných. Pracovali jsme s různými druhy dat a Perl si je v tichosti sám podle nějakých pravidel konvertoval.

To v Perlu 6 zůstává, ale nově bude existovat i možnost explicitního uvedení datového typu programátorem při deklaraci proměnné.

#!/usr/bin/env perl
my Str $retezec1 = "1";
my Str $retezec2 = "cokoliv";
my Int $cislo = 1;
say $retezec1;          #tiskne 1
say $retezec1 + $cislo; #tiskne 2 - také v pořádku, k vyhodnocení se použije konverze
                        # řetězce na číslo
say $retezec2 + $cislo; #tiskne 1 - také v pořádku, obsah $retezec2 byl vyhodnocen jako 0
$cislo = "cokoliv";     #chyba - nelze přiřadit řetězec do celočíselné proměnné

K dispozici máme následující datové typy.

KódNázev
Anycokoliv (dynamické chování jako v Perlu 5; takto se chovají proměnné bez deklarace)
Intcelé číslo
Strřetězec
Numčíslo
Ratracionální číslo (zlomek)
Booltrue/false
NejakaTridaobjekt daného typu

Výraz lze testovat na datový typ pomocí v Perlu 6 oblíbeného operátoru "odpovídat si", který se zapisuje ~~. Například výraz 1 ~~ Int je pravdivý.

Lze definovat vlastní datové typy. Například datový typ pro sudá čísla bychom definovali takto.

subset Even of Int where { $_ % 2 == 0 }

Rozepisování datových struktur

Pro pohled do nitra datové struktury jsme se naučili používat modul Data::Dumper. Nyní ale pro základní orientaci postačí následující.

my $a = [(1, 2), (3, 4), [5, 6]];
say $a.perl; # vytiskne řetězec [(1, 2), (3, 4), [5, 6]]

Přetěžování kontextu

V Perlu 5 máme funkci scalar, která vynutí skalární kontext. V Perlu 6 lze již vynutit libovolný kontext. Následující tabulka uvádí, jak vynutit jednotlivé (již specializovanější než jen prázdný, skalární a pole) datové typy.

SyntaxeVýznam
~něcořetězec
?něcoboolean
+něcočíslo bez znaménka
-něcočíslo se znaménkem
$(něco)skalár
@(něco)pole
@@(něco)řez polem (narozdíl od kontextu pole řezy vzájemně neinteragují)
%(něco)hash

Díky této změně budeme moci zjednodušit spoustu zápisů. Jak bychom například v Perlu 6 zjistili neprázdnost pole?

Podprogram MAIN

Podprogram s názvem MAIN si automaticky vezme parametry z příkazového řádku. Ukažme si, jak to lze použít.

sub MAIN ($arg1, $arg2) {
    say "Parametry: $arg1 $arg2";
}

A teď se podívejme, jak bude program reagovat na volání.

$ perl6 main.pl 1 2
Parametry: 1 2
$

Co když uvedeme jiný počet parametrů? Pak se automaticky zavolá podprogram USAGE, který implicitně vytiskne následující zprávu.

$ perl6 main.pl 1 2 3 4 5
Usage:
add.pl arg1 arg2
$

Pokud místo klíčového slova sub uvedeme multi, lze vytvořit různé MAIN pro různé prototypy. Také lze zadávat parametry --arg1 --arg2.

Pojmenování parametrů v hlavičce podprogramů, konec @_

V hlavičce podprogramů je třeba v Perlu 6 pojmenovat parametry, protože již nebudeme používat proměnnou @_. Podprogramy tak budou vypadat následovně.

sub nadruhou($cislo){
  return $cislo ** 2;
}

I zde je možné explicitně uvést datový typ.

sub nadruhou(Rat $cislo){
  return $cislo ** 2;
}

Důležité však je, že tyto parametry budou pouze pro čtení a při pokusu o změnu jejich hodnoty bude vyvolána výjimka. Toto chování lze změnit atributem is rw.

Existují tři módy předávání parametrů:

  • Poziční - Klasické parametry u nichž záleží na pořadí.
  • Pojmenované - Jsou předávány pomocí svého jména, nezáleží na seřazení a deklarují se znakem :
  • Srkající (slurpy) - Tyto proměnné absorbují všechny neabsorbované parametry a označují se znakem *. Pole takto označené absorbuje všechny poziční jinam nezařazené parametry a hash pohltí ty pojmenované.

Parametry mohou být povinné i nepovinné. Standardně jsou povinné a pro změnu chování je třeba uvést za pojmenovaný parametr znak ! a za poziční znak ?. Srkající parametry jsou vždy nepovinné.

Podívejme se na příklad, který ukazuje chování dvou různých volání.

sub funkce($pozicni, :$pojmenovany, *@srkajici){
    ...
}
funkce(1, 2, 3);                         # $pozicni=1, $pojmenovany=2, @srkajici=(3)
funkce(:pozicni<1>, :pojmenovany<2>, 3); # $pozicni=1, $pojmenovany=2, @srkajici=undef

Enumerace

Pomocí následujícího kódu lze vytvářet něco jako speciální datový typ pro konečné množství hodnot.

enum Rok (2011 2012 2013);

Hodnotu pak reprezentujeme jako Rok::2011.

Změny v cyklech

for a while cyklus můžeme psát v nové syntaxi. V jedné iteraci můžeme ze seznamu převzít i více než jeden prvek.

for @seznam -> $i, $j {
    say "Máme prvky $i, $j.";
}

Céčkovský for cyklus je nyní přejmenován na loop. Cyklus loop {} se dá také použít jako nekonečná smyčka.

Operace se soubory

Koncept handlerů z Perlu 5 samozřejmě funguje dále. Perl 6 ale nabídne několik zajímavých usnadnění. Podívejme se, jak budeme moci otevřít soubor a číst z něj.

my $fh = open "nejaky_soubor";
print $fh.get;  # tiskne řádek
print $fh.getc; # tiskne znak
$fh.close

Jak vytvoříme nový soubor (analogie unixového touch)?

open("novy_soubor", :w).close

A co zápis?

open "nejaky_soubor", :w;
$fh.say("toto zapíšeme do souboru");
$fh.print("toto taky");

Za zmínku stojí též funkce slurp s názvem souboru jako parametrem, která vrátí obsah souboru.

Změnilo se také testování souborů. Nyní budeme testovat pomocí nového operátoru ~~ pro "odpovídání si", se kterým můžeme porovnávat skoro všechno se vším. Ještě se s ním setkáme později. Například existenci souboru ověříme následovně.

if ("jmeno_souboru".IO ~~ :e){
    say "existuje";
}

Změny v OOP

V Perlu 5 vznikaly objekty pomocí funkce bless. To je možné stále, ale existuje nově také paralelní model, který je inspirován i již existujícím Moose.

Okamžitě viditelnou je změna operátoru šipky na tečku při přístupu k metodám a atributům.

Takto bychom mohli začít psát třídu pro manipulaci s komplexními čísly. Musíme deklarovat atributy pro reálnou a imaginární část pomocí deklarátoru has. Atributy se označují uvedením tečky hned po sigil znaku.

class KomplexniCislo is rw {
    has $.re;
    has $.im;
}

Takto potom vytvoříme číslo 1 + 2i.

my $komplex = KomplexniCislo.new(re => 1, im => 2);

Dále s ním samozřejmě můžeme manipulovat.

$komplex.re = 3;
$komplex.im = 4;
say "Nová hodnota: ", $komplex.re, " + ", $komplex.im, "i"

Nové OOP bude podporovat role, které budou fungovat podobně jako v Moose. Role jsme již probrali dříve a proto zde jen uveďme, jak se budou v Perlu 6 používat.

class Organizmus {...}
class Clovek is Organizmus {...}
role Vareni {...}
class Kuchar is Clovek does Vareni {...}

Nyní bychom mohli tuto roli přiřadit konkrétnímu objektu.

my $clovek = new Clovek;
$clovek does Vareni;

Přípojky (junctions)

Přípojky jsou hodnoty, které se mohou vyskytovat ve více stavech. Jde o velmi zajímavou myšlenku, která se poprvé v Perlu objevila jako modul Quantum::Superpositions.

Zadefinujme proměnnou, která se bude vyskytovat v 5 stavech. Nejprve se podívejme na přípojku typu "any", která reprezentuje některou z hodnot.

my $mnozina1 = 0 | 1 | 2 | 3 | 6;

Nyní krátce zkoumejme vlastnosti této proměnné. Můžeme zkusit testovat, jaké číslo tato proměnná reprezentuje. Následující test dopadne úspěšně.

if 2 == $mnozina1 {
    say "2 je OK";
}

Zajímavé je, že úspěšně dopadne i následující test. U tohoto typu přípojky je totiž pro rovnítko lepší intepretací operace "být prvkem množiny".

if 2 == $mnozina1 == 3 {
    say "4 je OK";
}

Vybereme-li číslo mimo množinu, test neuspěje.

if 5 == $mnozina1 {
    say "5 je OK";
}

Leckoho napadne, jak se chová $mnozina1 při běžných aritmetických operacích.

say $mnozina1 * 2;

Asi ale nikoho nepřekvapí, že výsledným výrazem je další přípojka, protože je to jediný konzistentní způsob. Výraz se tedy vyhodnotí na any(0, 2, 4, 6, 12).

Ještě existuje druhý typ přípojky a to typ "all". Ta vyjadřuje všechny hodnoty.

my $mnozina2 = 1 & 2 & 5;

Rozdíl si můžeme ukázat například při porovnávání. Když porovnáváme dvě "any" přípojky mezi sebou, výraz je pravdivý, pokud existuje v první přípojce prvek, který je obsažen i ve druhé. Porovnáváme-li "all" přípojky, musí mít pro pravdivou hodnotu všechny stavy identické.

Při porovnávání "any" a "all" přípojky musí existovat každý stav "all" přípojky i v "any" přípojce. Následující výraz je potom nepravdivý.

$mnozina1 == $mnozina2

Dodejme, že nezávisí na pořadí prvků v přípojkách.

Měli bychom připomenou i to, že bitové operátory (jako které by přípojky identifikoval Perl 5) mají nyní novou syntaxi. Více v dokumentaci.

Poznamenejme, že s přípojkami souvisí ještě to, že výraz obsahující all(@pole) se může začít samovolně zpracovávat ve více vláknech. Uvedení all se totiž chápe tak, že nezáleží na pořadí, ve kterém se budou výrazy zpracovávat.

Využití může vypadat i takto.

if $p ~~ all(@regularni_vyrazy) {...}

Makra

Na okraj zmiňme také makra. V Rakudo Perlu zatím nejsou implementované, ale v budoucnu bude fungovat kód následujícího typu.

macro hello($what) {
    q:code { say "Hello { {{{$what}}} }" };
}

Další změny stručně

  • Pomocí operace transliterace lze nahradit tr///. Příkaz say "ABCA".trans("BCA" => "ZYX"); vypíše XZYX. Lze používat dvoutečkový operátor rozsahu.
  • Pro přehlednější výpis pole lze použít say ~@pole (vizte kontexty).
  • Funkce reverse dělala v Perlu 5 dvě věci - z pole udělala seznam pozpátku a v řetězci invertovala pořadí prvků. Nyní bude invertovat pouze seznamy.
  • Na invertování řetězce máme novou funkci flip.
  • Novou operací je inverze hashe. V hashi můžeme zaměnit klíče s hodnotami zápisem %invert = %hash.invert.
  • Pro práci s časem existuje funkce time vracející POSIXový čas a funkce now, která vrací objekt typu Instant, tj. tvaru Instant:2011-06-26T17:54:44.343521Z.
  • Počet prvků pole zjistíme pomocí @pole.elems, poslední index pomocí @pole.end.
  • Formáty končí - tyto věci nepatří do jádra jazyka a mohou být řešeny externími knihovnami.
  • Přetížit standardní chování funkce lze nejlépe pomocí multi sub GLOBAL::funkce.
  • Končí mimo jiné tyto operátory a funkce:
    • % je zobecněné.
    • Funkce pro DBM, jsou nahrazeny externími moduly, například DB_File.
    • each - nově máme metodu .pairs.
    • length - nově je třeba uvést jednotky, máme metody .chars a .bytes.
    • pos - lze použít $/.
    • ref - na typ můžeme testovat pomocí ~~ TYP.
    • tie - lze nahradit novými proměnnými, makry atd.
  • Končí autokvotace hashů. Nelze tedy psát %hash{klic}. Nově se použije buď %hash{'klic'} nebo %hash<klic>.
  • Řada vestavěných funkcí se stává metodami, například sort, print atd.
  • Místo blokového eval máme nově try, v němž můžeme použít blok CATCH.

Verze pro tisk

pridej.cz

 

DISKUZE

Nejsou žádné diskuzní příspěvky u dané položky.



Příspívat do diskuze mohou pouze registrovaní uživatelé.
> Vyhledávání software
> Vyhledávání článků

24.10.2014 17:45 /Petr Ježek
Hyper-Z pro radeony se vrací. Anreas Böll vydal patch umožňující opětovné povolení Hyper-Z v aktuální mesa 10.3 pro radeon R600g a radeonsi. Doporučuje se aplikovat, testovat a reportovat případné problémy před vydáním mesa10.4 v prosinci.
Komentářů: 1

24.10.2014 7:33 /MaReK Olšavský
Vyšlo Ubuntu 14.10 a spiny s dalšími desktopy Kubuntu 14.10, Xubuntu 14.10 a poprvé i Ubuntu-Mate (Lubuntu 14.10 bude opožděno). Změn je poměrně málo, nestihli zařadit aktuální GNOME a je bez convergence části.
Přidat komentář

24.10.2014 7:33 /MaReK Olšavský
Přípravy na vydání Debianu 8 jsou v plném proudu a nejednoho potenciálního uživatele by mohla zajímat připravovaná podpora multimédií pro novou verzi (jinak dosti konzervativní distribuce). Asi nebude potřeba používat obskurdní repozitáře kvůli podpoře přehrávání audia/videa a hudebníky nejspíše také potěší.
Přidat komentář

23.10.2014 7:13 /MaReK Olšavský
CERN používá OpenStack přibližně rok. Jaké je aktuální používání při výzkumu ukazuje článek na OpenSource.com. Vyprodukovaných dat, z měření, není malé množství a pro jejich zpracování je potřebný výkon několikatisíců serverů a pracovních stanic.
Přidat komentář

23.10.2014 7:13 /MaReK Olšavský
Prodejce starších her; jež jsou často hratelnější, než moderní grafické orgie; Good Old Games dosáhl milníku 100 her připravených pro Linux (nejde o portace, ale připravené konfigurace DOSBoxu/Wine).
Přidat komentář

23.10.2014 7:13 /MaReK Olšavský
O malou reklamu pro Ubuntu se postaral Andy Swan, se svým laptopem, při analýze počasí pro tragickou Velkou Cenu Japonska 2014 (Formule 1).
Přidat komentář

22.10.2014 7:19 /MaReK Olšavský
Programovacímu jazyku Swift, jenž nedávno zveřejnil Apple a je uzavřený, vzniká svobodná odpověď Phoenix (repozitář). Jazyk bude stejný, takže lze očekávat, že se Apple bude bránit i soudně. Název Phoenix už nejspíše také někdo používá, starší pamatují, že se tak chvíli jmenoval dnešní Mozilla Firefox.
Přidat komentář

22.10.2014 7:19 /MaReK Olšavský
Programátorům v PHP je určen nástroj RIPS, který jim pomůže odhalit zranitelnosti v jejich kódu. Pokud znáte další nástroje, podělte se o ně v diskusi.
Přidat komentář

   Více ...   Přidat zprávičku

> Poslední diskuze

24.10.2014 17:47 / Petr Ježek
Andreas

16.10.2014 7:56 / Leo
Sanba

13.10.2014 7:20 / MaReK Olšavský
Re: PDF a podpis

10.10.2014 8:01 / Hynek Beran
PDF a podpis

10.10.2014 7:41 / Dusan Hlavac
Re: Takže nic.

Více ...

ISSN 1801-3805 | Provozovatel: Pavel Kysilka, IČ: 72868490 (2003-2014) | mail at linuxsoft dot cz | Design: www.megadesign.cz | Textová verze | zákony online