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)