Perl 6
Raku (původně Perl 6) je dynamický programovací jazyk, který vzniká celkovým přepracováním Perlu.
Larry Wall, původní autor Perlu, nazývá Perl 6 „přepracování Perlu a komunity komunitou“ („community's rewrite of Perl and of the community“), protože jedny z nejvýznamnějších změn provedl na základě 361 RFC (žádosti o komentáře), které mu byly zaslány v roce 2000.[1] Larry uspořádal tyto změny do série esejí (Apocalypses), kde nastínil které změny se mu líbí, které ne a které ještě zváží. Tyto dokumenty jsou nyní považovány za historické. Nynější, zatím nedokončená a neustále se vyvíjející specifikace Perlu 6 je uvedena v dokumentech s názvem Synopses. Číslování Apocalypses a Synopses odpovídá jednotlivým kapitolám v knize Programování v Perlu.
Perl 6 je přepracování jazyka, jež přináší elementy z moderních i historických jazyků. Výrazně se liší od předchozích verzí Perlu a nebude zpětně kompatibilní na úrovní zdrojových kódů. Kód a především moduly v Perlu 5 však bude možné dále používat.
Perl 6 je vyvíjen již přes šest let. Ale zatím neexistuje úplná implementace Perlu 6. V projektu Pugs je již větší část vlastností jazyka hotova, ale nevýhodami jsou malá rychlost a nekompatibilita licencí některých částí kódu. Existují další dvě implementace, jedna v Parrotu na základě PGE, nazvaná Rakudo Perl, a druhá v Perlu 5, který je součástí projektu Pugs. Práce na projektu Pugs byla zastavena, naopak první release Rakuda, nazvaný také Rakudo Star, byl uvolněn v červenci 2010.
Hlavní změny oproti Perlu 5
Perl 5 a Perl 6 jsou velmi rozdílné jazyky, přesto hlavním záměrem bylo aby „Perl 6 byl stále Perl“. Mnoho změn má standardizovat jazyk a udělat jej snadnějším pro naučení ať již pouze základům nebo hodně do hloubky. Pokračuje tedy ve vývoji a dělá jednoduché věci ještě více jednoduššími a umožňuje dělat více složitých věcí (easy things easier and hard things more possible).
Specifikace
Hlavní netechnický rozdíl mezi Perlem 5 a Perlem 6 je, že Perl 6 začal specifikací jazyka. To znamená, že Perl 6 může být reimplementován, pokud to bude nutné, a také to, že programátor nemusí číst zdrojové kódy, aby získal úplnou informaci o některé z vlastností. Dokumentace Perlu 5 je považovaná za velmi kvalitní, ale pokud se dokumentace a zdrojové kódy interpretu Perlu 5 liší, pak jsou právě zdrojové kódy považovány za správný stav a dokumentace by měla být změněna. Jinak řečeno specifikace Perlu 5 je dána existujícím interpretem, přesná specifikace v podobě klasického textu neexistuje.
Typový systém
V Perlu 6 byl dynamický typový systém rozšířen o možnost uvést statické typy:
my Int $i = 0;
my Num $n = 3.142;
my Str $s = "Hello, world";
Avšak, stejně jako v Perlu 5, programátor může většinu věcí dělat bez explicitního vyjádření typu:
my $i = "25" + 10; # proměnná $i má nyní hodnotu 35
Zastánci statického typování uvádějí že je výhodné pro optimalizaci v kompilátoru, snižuje počet chyb programátora a zvyšuje udržovatelnost, zvláště u velkých projektů.
Na druhou stranu dynamické typování snižuje délku zdrojového kódu, což je důležité u malých projektů. Velmi se to projevuje u rychlého psaní jednořádkových či krátkých skriptů nebo skriptů na jedno použití.
Perl 6 tedy nabízí hybridní typový systém a programátor si tedy může zvolit zda bude používat statické nebo dynamické typování nebo obojí najednou.
Definice parametrů podprogramů
Při předání parametrů do podprogramu v Perlu 5 je „vytvořeno“ pole aliasů na tyto parametry označené @_. Pokud je pole @_ modifikováno, pak se změna může projevit v originálních předávaných datech.
Perl 6 již má skutečné formální parametry. V Perlu 6 může definice podprogramu vypadat třeba takto:
sub udělej_něco(Str $text, Int $číslo) { ... }
Tyto parametry jsou defaultně jen pro čtení. Nelze tedy měnit jejich hodnotu. Pro čtení i zápis (read-write) je možné je označit direktivou is rw
. Pokud je označíme is copy
, pak je možné je měnit lokálně.
Předávání parametrů
Perl 6 poskytuje tři základní typy předávaní parametrů:
- Poziční (Positional)
- Pojmenované (Named)
- Srkající (Slurpy)
Poziční parametry jsou klasický seznam seřazených parametrů, který používá většina programovacích jazyků. Všechny parametry mohou být také předány pomocí jejich jména v neseřazené formě. Pojmenované parametry mohou být předány pouze pomocí svého jména (což znamená, že nejsou nikdy předávány jako poziční) a jsou označeny pomocí znaku :
před jménem. Srkající (slurpy) parametry (označené pomocí *
před nimi) jsou nástrojem Perlu 6 pro funkce s proměnným počtem parametrů (en:variadic functions). Srkající hash bude obsahovat všechny zbývající pojmenované parametry, zatímco srkající pole bude obsahovat všechny zbývající parametry předané pozičně.
Ukázka používající všechny tři možnosti předávaní parametrů:
sub somefunction($a, $b, :$c, :$d, *@e) {...}
somefunction(1, 2, :d(3), 4, 5, 6); # $a=1, $b=2, $c=Nil, $d=3, @e=(4,5,6)
Poziční parametry jako ty v příkladu jsou povinné, pokud za nimi není uveden znak ?
, který vyjadřuje že jsou nepovinné. Pojmenované parametry jsou standardně nepovinné, pokud nejsou označeny znakem !
za jménem proměnné. Srkající parametry jsou vždy nepovinné.
Bloky a uzávěry
Parametry mohou být rovněž poslány do libovolného bloku, který se chová jako uzávěr. Je to způsob, jak jsou např. iterátory while smyčky pojmenovány. V následujícím příkladu je procházen seznam po třech elementech najednou a ty jsou předávány do loop bloku jako proměnné $a, $b, $c.
for @list -> ($a, $b, $c) { ... }
Obecně je tento způsob nazýván „nečisté podprogramy“ (pointy sub) nebo „nečisté bloky“ (pointy block), u nichž se šipka chová téměř úplně stejně jako klíčové slovo sub. Tento způsob zavádí do jazyka anonymní uzávěry (closure) (nebo anonymní podprogramy (subroutine) při použití terminologie Perlu 5).
Neměnnost sigils
V Perlu 5 se sigils — interpunkční znak před samotným jménem proměnné — mění podle toho jak je proměnná použita:
# Perl 5 code
my @array = (1, 2, 3);
my $element = $array[1]; # $element equals 2
V Perlu 6, sigils jsou invariantní, což znamená, že se nemění podle toho zda jde o pole nebo o prvek pole:
# Perl 6 code
my @array = (1, 2, 3);
my $element = @array[1]; # $element equals 2
Změna sigil v Perlu 5 byla inspirovaná přirozenými jazyky:
"To jablko". # SPRÁVNĚ "Ta jablka. # SPRÁVNĚ "To jedno třetí jablko z jablek". # SPRÁVNĚ "Ta jedno třetí jablko z jablek". # ŠPATNĚ
Změna v Perlu 6 má snížit en:cognitive load při rozeznávání zda použít @ nebo $.
Objektově orientované programování
Perl 5 podporoval objektově orientované programování přes mechanismus známý jako požehnávání (blessing). Jakákoliv reference mohla být „požehnána“ (blessed) do stavu objektu určité třídy, požehnaný objekt mohl mít metody volatelné na něm pomocí „šipkové notace“ (arrow syntax), která v Perlu 5 měla za následek statické vyhledání nebo dynamické vyhledání (dispatch) příslušného podprogramu podle jména a jeho zavolání tak, že požehnaná proměnná byla prvním argumentem.
I když jde o extrémně mocný model, prakticky jakýkoliv objektový model jiného programovacího jazyka je možné tímto jednoduchým modelem simulovat, tak na druhou stranu běžné případy objektově orientovaného programování, jako např. jednoduchá kompozice objektů s nějakým přidruženým kódem, jsou zbytečně složité. Navíc, protože Perl nemůže dělat žádné předpoklady o tom zda je použit objektový model, tak nemůže ani příliš dobře optimalizovat volání metod.
V duchu dělání „jednoduchých věcí jednoduchými a složitých možnými“, Perl 6 zachovává model požehnávání, ale podporuje také mnohem robustnější model pro běžné případy.[2] Například, třída zapouzdřující bod v Kartézské souřadnicové soustavě může být definována a použita takto:
class Bod is rw {
has $.x;
has $.y;
}
my Bod $bod .= new( :x<1.2>, :y<-3.7> );
# Nyní změníme x (všimněte si, že metoda "x" je použita jako lhodnota):
$bod.x = 2;
say "X-ová souřadnice bodu: ", $bod.x;
Šipka je nahrazena tečkou, což je mnohem běžnější syntaxe (Java, Python, atd.) pro volání metod.
V terminologii Perlu 6 je $.x
nazýván „atribut“ (attribute). Jiné jazyky nazývají atribut položkou (field) nebo prvkem (member). Metoda používaná pro přístup k atributu je nazývána „accessor“ (accessor). Auto-accessors jsou metody, které jsou vytvářeny automaticky jako např. metoda x
v příkladu výše. Tyto accessor funkce vrací hodnotu atributu. Pokud je třída nebo jednotlivý atribut deklarován s is rw
modifikátorem (rw je zkratka pro „read/write“, tj. „čtení/zápis“), auto accesoru může být poslaná nová hodnota jako parametr pro nastavení atributu nebo mu může být použit přímo jako hodnota pro přímé přiřazení (jako v příkladu výše). Auto accesor může být nahrazen jinou uživatelsky definovanou metodou, pokud programátor požaduje složitější přístup k atributu. K atributům je možné přistupovat přímo pouze z vnitřku třídy. Všechny ostatní přístupy mohou být uskutečněny pouze pomocí accessor metod.
Role
Role v Perlu 6 jsou možností jak použít jak interfaces z Javy tak traits[3] z varianty Squeak Smalltalku. Jsou podobné třídám, ale jsou zcela abstraktní. Při použití s třídami jsou způsobem kompozice bez zasahování do pole dědičností (inheritance chain) třídy. Role definují nominální typy; poskytují sémantické jména pro soubor chování a stavu.
Základním rozdílem mezi rolemi a třídami je to, že ze třídy je možné vytvořit instanci objektu (are instantiable), zatímco z rolí ne.[4]
V podstatě je role balík (eventuálně abstraktních) metod a atributů, které mohou být ke třídě přidány bez použití dědičnosti. Role může být přidána také k individuálnímu objektu, v tomto případě Perl 6 vytvoří anonymní podtřídu (anglicky), přidá roli k této podtřídě a změní třídu objektu na takto vzniklou anonymní podtřídu (s rolí).
Např. pes je savec. Psi dědí některé vlastnosti od savců, např. mléčné žlázy a také, protože savci jsou obratlovci, páteř. Psi mohou mít jednu nebo několik různých typů chování, např. pes může být domácí mazlíček, pes divoký nebo vodicí pes pro nevidomé. Avšak toto jsou jednoduché soubory dodatečných vlastností, které mohou být přiřazeny jak ke psovi, tak v případě vlastností "mazlíček" či "divoký" také např. ke kočce. Proto pes a savec jsou třídy, zatímco mazlíček, divoký a vodicí jsou role.
class Savec is Obratlovec {...}
class Pes is Savec {...}
role Mazlící {...}
role Divoký {...}
role Vodicí {...}
Role jsou přidávány třídě nebo objektu pomocí klíčového slova does
(dělá) na rozdíl od klíčového slova is
(je) pro dědičnost. Klíčové slova odrážejí rozdílný význam těchto dvou vlastností: přidání role dává třídě "chování" této role, ale nenaznačuje, že se jedná o "stejnou věc" jako je tato role.
class VodicíPes is Pes does Vodicí {...} # přidání role k podtřídě
my $pes = new Pes;
$pes does Vodicí; # přidání role k individuálnímu objektu
I když se role liší od tříd, obě jsou typy. Proto se role může vyskytovat v deklaraci proměnné, tam kde běžně bývá třída. Např. role "Nevidomý" u člověka může obsahovat atribut typu "Vodicí" a tento může obsahovat hodnotu vodicí pes, vodicí kůň, vodicí člověk nebo vodicí stroj.
class Člověk {
has Pes $pes; # Může obsahovat psa, ať už má, či nemá roli Vodicí
...
}
role Nevidomý {
has Vodicí $vodič; # Může obsahovat jakýkoliv objekt, který má roli Vodicí,
... # ať už je to Pes nebo něco jiného
}
Regulární výrazy
Regulární výrazy a podpora pro zpracování textů jsou jedněmi z vlastností, které definují Perl.[5] Možnosti pro rozeznávání vzorů (pattern-matching) Perlu již před nějakou dobou překračují klasické formální regulární výrazy, proto jsou v dokumentaci Perlu 6 nazývány výhradně termínem regexes, který je odlišný od formální definice.
Regexes Perlu 5 jsou součásti mnohem větší množiny funkcí nazývaných pravidla (rules), které obsahují možnosti kontextových parserů (jak např. syntactic predicates of parsing expression grammars and ANTLR) stejně jako možnost chovat se jako uzávěry (closures) respektující jejich lexikální (statický) rámec (lexical scope) .[6] Pravidla se definují pomocí klíčového slova rule
podobně jako podprogramy. Anonymní pravidla mohou být definována pomocí regex
(nebo rx
) nebo mohou být použita uvnitř (inline) stejně jako tomu bylo v případě regexps Perlu 5 přes m
(srovnej (matching)) nebo s
(hledej a nahraď (search and replace)) operátory.
V Apocalypse 5, Larry Wall napočítal 20 problémů se „stávající kulturou regex výrazů (current regex culture)“. Mezi nimi bylo to, že regexes Perlu byly „příliš kompaktní (compact) a ‚roztomilé (cute)‘“, měly „příliš mnoho důvěry v příliš málo operátorů“, „slabou podporu pro pojmenované zachycení (captures)“ a „slabou podporu integrace se ‚skutečnými‘ jazyky“.[7]
Zjednodušení syntaxe
Některé konstrukce Perlu 5 byly v Perlu 6 změněny tak, aby byly vhodnější pro odlišná syntaktická pravidla pro nejpoužívanější případy. Např. kulatá závorka vyžadovaná pro řídící struktury (control flow) v Perlu 5 je nyní nepovinná:[8]
if is_true() {
for @array {
...
}
}
Také operátor ,
(čárka (comma)) je nyní konstruktor seznamu (list), proto nejsou obklopující závorky rovněž vyžadovány. Kód
@pole = 1, 2, 3, 4;
vytváří pole (array) @pole s obsahující prvky (elements) '1', '2', '3' a '4'.
Zřetězené porovnávání
Perl 6 umožňuje porovnávat v „řetězci“ (chain), což znamená že sekvence porovnávání jako např. následující jsou dovoleny:
if C(20) <= $teplota <= C(25) { say "Pokojová teplota!" }
Tento výraz je zpracován jako kdyby každé porovnání postupně zleva doprava bylo provedeno zvlášť a výsledek byl logicky spojen pomocí operace and
.
Líné vyhodnocování
Perl 6 používá techniku líného vyhodnocování seznamů, která je součástí funkcionálních programovacích jazyků mezi které patří např. Haskell:[9]
@cela_cisla = 0..Inf; # celá čísla od 0 do nekonečna
Výše uvedený kód je validní, tj. nepokouší se přiřadit seznam nekonečné délky do pole @cela_cisla
ani nezůstane navždy „viset“ (hang indefinitely) při pokusu rozšířit seznam pokud prohledáváme omezený počet jeho položek (slots).
Tento přístup zjednodušuje mnoho částí Perlu 6, např. vstupně/výstupní operace, transformace seznamů a předávání parametrů.
Junctions (Propojky)
Perl 6 představuje koncept junctions: hodnot, které jsou složeny z jiných hodnot.[9] Na začátku návrhu Perlu 6 se jim říkalo „superpozice“ (superpositions), analogicky ke konceptu kvantové superpozice z kvantové fyziky, kde se vlny mohou najednou vyskytovat ve více stavech dokud je pozorovatel „nezhroutí“. Perl 5 modul Quantum::Superpositions
[10] vydaný Damianem Conwayed v roce 2000 poskytl první návrh (proof of concept). Na začátku vypadaly superpoziční (superpositional) hodnoty jako programátorská kuriozita, v průběhu času byla jejich užitečnost a intuitivnost široko rozpoznána a junctions nyní patří k hlavním částem návrhu Perlu 6.
V nejjednodušším případě jsou propojky (junctions) spojením množiny hodnot pomocí propojovacího (junctive) operátoru:
my $jakákoliv_sudá_číslice = 0|2|4|6|8; # any(0, 2, 4, 6, 8)
my $všechny_liché_číslice = 1&3&5&7&9; # all(1, 3, 5, 7, 9)
|
označuje hodnotu, která je rovna buď jeho levému nebo pravému argument. &
označuje hodnotu, který je rovna jeho levému a zároveň i pravému argumentu. Tyto hodnoty mohou být použity kdekoliv v kódu jako normální hodnoty. Operace vykonané na propojce (junction) se chovají ke všem prvkům propojky stejně a jsou uspořádány podle operátoru propojky. Proto výsledkem ("ananas"|"banán") ~ "y"
je "ananasy"|"banány"
. Při porovnávání propojka vrací jeden výsledek, true (pravda) nebo false (lež). |
nebo any
propojka vrací true, pokud je porovnání pravdivé pro alespoň jeden prvek propojky. &
nebo all
propojka vrací true, pokud je porovnání pravdivé pro všechny prvky propojky.
Propojky mohou být také použity pro rozšíření typového systému na způsob generického programování, které je omezený propojkami typů:
sub get_tint ( RGB_Color|CMYK_Color $color, num $opacity) { ... }
sub store_record (Record&Storable $rec) { ... }
Autothreading
Junctions (propojky) jsou neseřazené; 1|2|3
a 3|2|1
představují stejnou hodnotu. Díky tomu může kompilátor Perlu 6 zvolit paralelní zpracování výrazu s propojkou. Např. kód:
for all(@pole) { ... }
naznačuje kompilátoru, že for
smyčka by měla být spuštěna paralelně, třeba v oddělených vláknech (threads). Tato vlastnost je nazývána „autothreading“ (automatické spouštění ve vláknech). Použití a implementace není zatím zcela dokončena a je otázkou pro diskuse vývojářů.[11]
Makra
V nízkoúrovňových jazycích (například v preprocesoru C) jsou makra používaná k nahrazování textu ve zdrojovém kódu. Vysokoúrovňové jazyky (například Lisp) mají makra, která jsou mnohem více sofistikovaná. Perl 6 používá vysokoúrovňový koncept maker, makra v Perlu 6 pracují s programem jako s datovou strukturou. V definicích maker je možno používat všechny vlastnosti samotného jazyka.
Definice makra v Perlu 6 vypadá jako definice funkce nebo metody a může pracovat nad neparsovanými řetězci, nad syntaktickým stromem nebo nad jejich kombinací. Definice makra může vypadat takto:[12]
macro hello($what) {
quasi { say "Hello { {{{$what}}} }" };
}
V tomto případě makro provádí nahrazení textu podobně jako v jazyce C, avšak protože parsování parametru makra je provedeno předtím, než dojde k nahrazení, budou chybové hlášky přesnější. Tělo makra je provedeno v čase kompilace pokaždé, když je makro použito, a je tedy možno výsledný kód snadněji optimalizovat. Správně použitými makry je možné zcela eliminovat složité výpočty a provést je v čase kompilace.
Hello world
Program hello world je často používán k demonstraci základního použití jazyka. V Perlu 6 může být napsán takto:
say "Hello world"
Funkce say
, která je v Perlu 6 nová, tiskne své parametru (podobně jako funkce print
), ale se znakem nového řádku na konci.
Reference
- Wall, Larry. Apocalypse 1: The Ugly, the Bad, and the Good [online]. 2001-04-02. Dostupné online.
- Wall, Larry. Synopsis 12: Objects [online]. 2006-08-18. Dostupné online.
- The Software Composition Group. Traits [online]. 2003 [cit. 2007-06-26]. Dostupné v archivu pořízeném dne 2006-08-11.
- chromatic. Roles: Composable Units of Object Behavior [online]. 2006. Dostupné online.
- Parlante, Nick. Essential Perl: String Processing with Regular Expressions [online]. 2000. Dostupné online.
- Wall, Larry. Synopsis 5: Regexes and Rules [online]. 2002-06-24. Dostupné online.
- Wall, Larry. Apocalypse 5: Pattern Matching [online]. 2002-06-04. Dostupné online.
- Wall, Larry. Synopsis 4: Blocks and Statements [online]. 2004-08-19. Dostupné online.
- Wall, Larry. Synopsis 9: Data Structures [online]. 2004-09-13. Dostupné online.
- Conway, Damian. Quantum::Superpositions - QM-like superpositions in Perl [online]. 2002. Dostupné online.
- Adams, Rod. Junction Values [online]. 2005-02-15. Dostupné online.
- Macros [online]. [cit. 2014-01-05]. Dostupné v archivu pořízeném dne 2014-01-06. (anglicky)
Externí odkazy
Specifikace
- Synopses – dokumenty považované za oficiální, ale vyvíjející se, specifikaci jazyka.
- Exegeses – Vysvětlení Apocalypse s příklady
- Apocalypses – První návrhy Larry Walla
- RFCs – Originální žádosti komunity o úpravy jazyka
- Perl 6 Dokumentace s částmi testů jazyka
Implementace
Ostatní
- perl6.cz – Web pro české uživatele s unikátním seznamem odkazů
- Planet Perl 6 – Agregátor Perl 6 blogů.
- Present Continuous, Future Perfect – Přednáška Larry Wall o Perlu 5 and Perlu 6 na Open Source Developer Conference 2006 v Netanya, Israel (HTML s odkazem na slidy a audio nahrávku)
- Perl 6 FAQ[nedostupný zdroj] – Otázky a odpovědi na nejrůznější otázky.
- Perl 6 Quick-Start[nedostupný zdroj] – Krok za krokem jak napsat svůj první Perl 6 program a jak jej spustit
- Perl6::Perl5::Differences