Přednáška #10: Perl 6 (http://www.perl6.org/) ##################### Specifikace =========== apokalypsy a exegeze původní návrh jazyka synopse formální specifikace STD formální gramatika roast formální testy Překladače ========== Rakudo -> Parrot, JVM, MoarVM Niecza -> CLR/.NET Pugs interpret v Haskellu (neudržován) viv překladač do Perlu5 Perlito (MiniPerl6) P5/P6 -> P5/P6, JavaScript, Python inspiruje Perl5 ~~, given, Moose, ... Základní rozdíly oproti P5 ========================== use v6; dlouhý-utf8-ident mezery mouhou být signifikantní: $a{...} vs. $a {...} -> v řídicích konstrukcích se nemusí psát závorky reforma sigilů: - indexováním pole se nemění sigil: @a[1] - automatické (de)referencování -> $a může být např. pole - sigil udává druh rozhraní, ne druh dat <-- zkratka pro qw{...} <> <-- totéž interpolující (může být unicodové) @a<1 4 5> <-- zkratka pro @a[ <1 4 5> ] ~ <-- nyní operátor pro zřetězení $owl.hoooot <-- tečka volá metody a => 1 <-- objekt typu Pair @a[1; 3] <-- vícerozměrná pole $_ je lexikálně lokální, funguje např.: .hoot <-- zavolá metodu aktuálního objektu cykly: for @xyz { kód } <-- nastavuje $_ for @xyz -> $a { kód } <-- nastavuje $a for @xyz -> $a, $b { kód } <-- iteruje po dvojicích (ve skutečnosti je -> zápis lambda-funkce) * ("whatever") $x ~~ 1..* ($a, $b, $c) = "ouha" xx * <-- líný seznam (*, *, $a) = (1, 2, 3) @pole[*-1] <-- poslední prvek pole deklarace: my $x; <-- lexikálně lokální our $x; <-- lexikání alias pro proměnnou balíčku state $x; <-- jako my, ale pamatuje si minulou hodnotu temp $x = 1; <-- jako local v P5 nepovinné typování: my Int $dog; my Cat @cattery[10]; <-- typ prvku pole, explicitní velikost my Array of Dog @kennels; my Dog|Cat $pet; my @dogs is Database; interpolace: $x interpoluje vždy konstrukce končící závorkami také: $a.metoda() pole jen končí-li závorkami: @a[] { ... } undef neexistuje nahrazen nedefinovanými objekty jednotlivých typů, Mu je generický builtiny při chybách vracejí výjimky, které se chovají jako undef Sigily a twigily ================ $a <-- skalár (autodereferencovaný) @a <-- pole, expanduje se při použití %a <-- hash & <-- subrutiny, regulární výrazy apod. :: <-- balíčky, typy, atd. $*name <-- globální proměnné (třeba $*IN, @*ARGV) $.attr <-- veřejný atribut objektu $!attr <-- soukromý atribut objektu $?name <-- proměnná překladače atd. Příslovečné konstrukce (adverbial forms) ======================================== :a <-- a => True :!a <-- a => False :a(x) <-- a => x :$a <-- a => $a :a <-- a => Operátory ========= [ a, b, c ] <-- konstruktor pole { a => b, ... } <-- konstruktor hashe ?x ~x +x <-- vynucení kontextu (bool, string, numeric) +& +| +< <-- numerické verze (and, or, posun doleva) 1 +> 5 :signed :rotate <-- modifikace adverbiem ~& ~| ~< <-- bufferové verze (pro pole bajtů) ?& ?| <-- booleovské verze (nezkracují) %% <-- je dělitelné x xx <-- replikace (řetězcová a seznamová) === <-- identita (pozor, řetězce jsou neměnné) == eq <-- numerická a stringová rovnost jako v P5 eqv <-- stejný typ a struktura <=> leg cmp <-- třícestné porovnání (číselné, stringové, generické) a & b & c <-- junction a < b < c <-- řetězené porovnání ~ <-- konkatenace ~~ <-- smart-match // <-- default min max lcm gcd a ?? b !! c <-- podmínka Z X <-- zip, kartézský součin 1..5 1..^5 ^5 <-- generátor (líného seznamu) 1,3,...,* <-- magický generátor 1, 1, {$^a + $^b}, ... * <-- Fibonacciho posloupnost :) {rand} ... * <-- posloupnost náhodných čísel @a ==> map { $_^2 } ==> @b <-- feed operators @a := @b <-- vytvoření vazby (:== pro read-only vazbu) Meta-operátory ============== op= <-- kombinace s přiřazením !rel <-- negace relačního operátoru Rop <-- prohození operandů (třeba R<=>) <> <-- hyper-operátor (obrátit <<, nemá-li autorozšiřovat) @objects>>.method() [op] <-- redukce [max] @pole [<] @pole [+] () <-- vrátí 0 [\+op] <-- prefixová redukce [\+] 1,2,3 <-- 1, 1+2, 1+2+3 [\,] 1,2,3 <-- [1], [1,2], [1,2,3] Xop, Zop <-- zobecněný kartézský součin a zip Sop <-- sekvenční vyhodnocení Podprogramy =========== { kód } <-- uzávěr přes kód (každý blok je uzávěr) return, next, ... <-- interní výjimky leave <-- návrat z bloku -> $a, $b { kód } <-- lambda (<-> pro read-write argumenty) { $^a <=> $^b } <-- implicitní argumenty sub order-beer($type, $pints) { ... } Deklarace parametrů: $type = "Water" <-- default $type? <-- nepovinné bez defaultu $ <-- zahozen :$t <-- pojmenovaný: voláme f(t => 1) :$t! <-- pojmenovaný, ale povinný *@t <-- slurpy array (smlsne si na zbylých pozičních par.) *%t <-- slurpy hash (analogicky na zbylých pojmenovaných) |$args <-- předá objekt Capture se všemi argumenty $t is rw <-- read-write vazba $t is copy <-- předán hodnotou (kopií) Volání: f(1, 2, 3, named => 4, :adverb(5)) f(|@f, |%g) <-- dosazení argumentů f(|$args) <-- dosazení Capture Typování: sub add(Int $x, Int $y --> Int) ... Int $x where { 0 < $x < 100 } ... sub add(Numeric ::T $x, T $y --> T) sub add(...) is rw sub add(...) is export Funkce nezná svůj kontext, ale může vrátit polymorfní objekt Funkce se chová jako objekt: &f.assuming('arg') <-- fixování argumentu (currying) &f.signature <-- introspekce Multi-subrutiny: multi sub add(...) {...} Makra: vyhodnocována v čase překladu, mohou vracet syntaktický strom (WIP)