Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Perl 6 - The Butterfly Has Landed

Sidnet
February 29, 2016

Perl 6 - The Butterfly Has Landed

An overview of Perl 6 and some of its features. Created and presented by Michał Wojciechowski.

Sidnet

February 29, 2016
Tweet

More Decks by Sidnet

Other Decks in Programming

Transcript

  1. 2/73 Not a “Perl 5 ++” • Perl 6 and

    Perl (5) are different languages • Sometimes called “sister languages”, belonging to the same family • They share many concepts, but are not compatible • Still, “Perl 6 is Perl”
  2. 3/73 Some History • Designed by Larry Wall (creator of

    Perl (1-5)) • Language design started in 2000 • First intention was to get it ready in ~2 years • It actually took 15 years • - When will Perl 6 be released? - On Christmas! • Released in December 2015 (on Christmas)
  3. 5/73 Perl 6, Say Hello! • “Hello World” in Perl

    6: • As an oneliner: #!/usr/bin/env perl6 say 'Hello, World!' $ perl6 -e 'say "Hello, World!"'
  4. 6/73 Glossary/Bestiary • Perl 6 is the language specification (with

    the official test suite) • NQP (Not Quite Perl) is a subset of Perl 6 • Rakudo is a Perl 6 (and NQP) compiler • Rakudo Star is a Rakudo distribution • MoarVM is a virtual machine (runtime) • Rakudo can also target JVM (Java runtime)
  5. 9/73 Basic Syntax • if and unless: if $day eq

    'Saturday' || $day eq 'Sunday' { say 'You should not be working today.'; } elsif $hour !~~ 9..16 { say 'You should not be working at this hour.' } else { say 'Work work work!'; } unless $day eq 'Monday' { say "Yay! It's not Monday!"; }
  6. 10/73 Basic Syntax • with (like if defined): • given/when:

    with $score { $high_score = $score if $score > $high_score; } else { say "Score is not set"; } given $score { when 0..100 { say "You suck"; } when $_ > 9000 { say "IT'S OVER 9000!!!!11"; } default { say "Meh" } }
  7. 11/73 Basic Syntax • for: • loop (C-style for): loop

    (my $n = 10; $n > 0; $n--) { say $n; sleep 1; } say "Ignition!"; my @pets = ('cat', 'dog', 'hamster', 'porcupine'); for @pets -> $pet { say "One of my pets is a $pet"; }
  8. 12/73 Basic Syntax • while and until: • repeat while

    (and repeat until): while $foo < 3 { $foo++; } until $foo > 6 { $foo++; } repeat { $foo++; } while $foo < 3;
  9. 13/73 Basic Syntax • Comments: # Single line comment =begin

    explanation Multiline comment =end explanation say #`( Embedded comment ) "Hello!"; #`( Embedded comments can also be used for multiline comments )
  10. 15/73 Basic Data Structures • Scalars: • Arrays – autoextending:

    • Arrays – fixed-size: my $foo = 42; $foo = 3.14159; $foo = 'Om nom nom'; my @musketeers[3] = [ 'Athos', 'Porthos', 'Aramis' ]; @musketeers[3] = "D'Artagnan"; # Index 3 for dimension 1 out of range (must be 0..2) my @dinosaurs = [ 'Stegosaurus', 'T-Rex' ]; @dinosaurs[2] = 'Velociraptor';
  11. 16/73 Basic Data Structures • Arrays – multidimensional: • Hashes

    (key/value pairs): my @chessboard[1..8;1..8]; @chessboard[4;1] = '♕'; my %edges = (triangle => 3, square => 4, pentagon => 5); %edges{'hexagon'} = %edges{'pentagon'} + 1; say %edges<hexagon>; # 6
  12. 17/73 Ranges • Used to generate lists of consecutive numbers

    or strings: say [1 .. 5]; # [1 2 3 4 5] say [1 ^.. 5]; # [2 3 4 5] say [1 ..^ 5]; # [1 2 3 4] say [1 ^..^ 5]; # [2 3 4] say [^5]; # [0 1 2 3 4] my @alphabet = 'a' .. 'z'; say @alphabet[5 .. 10]; # (f g h i j k) say @alphabet[^5]; # (a b c d e)
  13. 18/73 Lazy Lists • List values aren't calculated until needed

    • Can be “infinite”: • Lazy lists made from other lazy lists: my @ints = 1 .. Inf; say @ints[12345]; # 12346 my @even_ints = grep * % 2 == 0, @ints; say @even_ints[12345]; # 24692 my @squares = map * ** 2, @ints; say @squares[12345]; # 152423716
  14. 19/73 Sequence Operator • Perl 6 can deduce what arithmetic/geometric

    sequence should be generated: • If it's unable to guess, we can tell it explicitly: my @numbers = 10, 20 ... *; say @numbers[^5]; # (10 20 30 40 50) my @powers_of_2 = 1, 2, 4 ... *; say @powers_of_2[^5]; # (1 2 4 8 16) my @seq = 1, { 2 * $_ + 3 } ... *; say @seq[^5]; # (1 5 13 29 61)
  15. 21/73 Types • Perl 6 is gradually typed, allowing for

    both dynamic and static typing • Comes with many built-in types, e.g.: – Int, Num, Complex – Str, Bool – Array, Hash, Pair – Regex, Code, Routine
  16. 22/73 Types • Dynamic typing: • Static typing: my $foo

    = 1.23; say $foo.WHAT; # (Rat) $foo = 'Bar'; say $foo.WHAT; # (Str) my Rat $foo = 1.23; $foo = 'Bar'; # Type check failed in assignment to $foo; # expected Rat but got Str
  17. 23/73 Subsets • Easily defined “subtypes” • Created by adding

    constraints to types: • Can be used ad-hoc (not named): subset EvenInt of Int where * % 2 == 0; my EvenInt $foo = 3; # Type check failed in assignment to $foo; # expected EvenInt but got Int sub hello(Str $name where *.chars > 0) { say "Hello, $name!"; }
  18. 25/73 Subroutines • Simplest example, no arguments: • Can be

    called with or without parentheses: • Without return, the last value is returned: sub hello { return "Hello, World!"; } say hello(); say hello; # Hello, World! (x2) sub hello { "Hello, World!"; }
  19. 26/73 Subroutines • Subroutine with an argument: • With an

    optional argument: sub hello($name) { "Hello, $name!"; } say hello('Chris'); # Hello, Chris! sub hello($name?) { "Hello" ~ (", $name" if $name) ~ "!"; } say hello('Martin'); # Hello, Martin! say hello; # Hello!
  20. 27/73 Subroutines • Argument with a default value: • Default

    value using a preceding argument: sub hello($name = 'World') { "Hello, $name!"; } say hello; # Hello, World! say hello('Jacob'); # Hello, Jacob! sub hello($name, $bangs = $name.chars) { "Hello, $name" ~ "!" x $bangs; } say hello('Mike'); # Hello, Mike!!!!
  21. 28/73 Subroutines • Argument with a type constraint: • Subroutine

    declared with a return type: sub hello(Str $name) { "Hello, $name!"; } say hello(321); # Calling hello(Int) will never work with declared # signature (Str $name) sub hello(Str $name) returns Str { "Hello, $name!"; }
  22. 29/73 Subroutines • Named argument: • Mandatory named argument: sub

    hello($name, :$title) { "Hello, " ~ ("$title " if $title) ~ "$name!"; } say hello('Tom', title => "Mr."); # Hello, Mr. Tom! sub hello($name, :$title!) { "Hello, $title $name!"; } say hello('Tom'); # Required named parameter 'title' not passed
  23. 30/73 Subroutines • Slurpy argument: • Read/write argument: sub hello(*@names)

    { "Hello, " ~ join(", ", @names) ~ "!"; } say hello('David', 'Victor'); # Hello, David, Victor! sub hello($name is rw) { "Hello, " ~ ($name = $name.uc) ~ "!"; } my $mario = 'Mario'; say hello($mario); # Hello, MARIO! say $mario; # MARIO
  24. 31/73 Anonymous Subroutines • Anonymous subroutine: • Pointy block (lambda)

    syntax: my &hello = -> $name { "Hello, $name!" }; say &hello('Pablo'); # Hello, Pablo! my &hello = sub ($name) { "Hello, $name!" }; say &hello('Pablo'); # Hello, Pablo! say hello('Pablo'); # Hello, Pablo! .say for map(-> $name { "Hello, $name!" }, 'Raph', 'Pete'); # Hello, Raph! # Hello, Pete!
  25. 32/73 Multiple Dispatch Subroutines • Same name, different signatures •

    Example: multi hello(Str $name) { "Hello, $name!"; } multi hello(Numeric $number) { "Hello, number $number!"; } say hello('Angie'); # Hello, Angie! say hello(123); # Hello, number 123!
  26. 34/73 Classes and Objects • At its core, Perl 6

    is object oriented • But, it doesn't impose the object oriented programming style • Perl 6's object system design was an inspiration for Moose, the popular Perl 5 object framework
  27. 35/73 Classes and Objects class Animal { has $species; #

    Implicit private has $!gender; # Explicit private has $.age; # Accessor has $.name is rw; # Read/write } my $moose = Animal.new( species => 'Alces alces', gender => 'male', age => 12, ); say $moose.age; $moose.name = 'Edward';
  28. 36/73 Classes and Objects class Item { has ($.name, $.price);

    } class ShoppingCart { has (@!items, $.total_price); method add_item(Item $item) { @!items.push($item); # Update a private attr $!total_price += $item.price; } } my $cart = ShoppingCart.new; $cart.add_item(Item.new(name => 'Beer', price => 3.50)); $cart.add_item(Item.new(name => 'Ketchup', price => 4.99)); say $cart.total_price; # 8.49
  29. 37/73 Classes and Objects class Item { has ($.name, $.price);

    } class ShoppingCart { has (@!items, $.total_price); method add_item(Item $item) { @!items.push($item); $!total_price += self!price_after_tax($item.price); } # Private method method !price_after_tax($price) { $price * 1.23 } }
  30. 38/73 Classes and Objects • Inherited class, using a role:

    role Talking { method introduce { say 'Hello, my name is ' ~ self.name; } } class TalkingAnimal is Animal does Talking { } my $moose = TalkingAnimal.new( species => 'Alces alces', name => 'Frank' ); $moose.introduce; # Hello, my name is Frank
  31. 39/73 Classes and Objects • Native types (like int or

    bool) are boxed into objects • Methods can be called on them, like with regular objects: my int $n = 7; say $n.WHAT; # (Int) say $n.is-prime; # True
  32. 41/73 Functional Programming • Perl 6 comes with many features

    that facilitate functional programming • Like with object orientation, it's up to the programmer to make use of these features or not • (This is what this multi-paradigm thing is about)
  33. 42/73 First-Class Functions • Functions/subroutines are first-class citizens • Can

    be passed as arguments: • Can be returned by other functions: sub percentage($value) { return $value * 100 ~ '%'; } say map(&percentage, 0.1, 0.5, 1.5); # (10% 50% 150%) sub multiply($factor) { return sub ($value) { return $factor * $value }; } my &triple = multiply(3); say triple(9); # 27
  34. 43/73 Junctions • “Superpositions” of multiple values that can be

    helpful for complex condition checking: if $code eq 'PL' || $code eq 'SE' || $code eq 'UK' { say "Sorry, payment in Euro not possible"; } if $code eq any('PL', 'SE', 'UK') { say "Sorry, payment in Euro not possible"; } if $code eq 'PL'|'SE'|'UK' { say "Sorry, payment in Euro not possible"; }
  35. 44/73 Junctions • Other junctions – all (&): • one

    (^): • none: my $password = 'Hunter1'; say 'Good' if $password ~~ all(/<[A..Z]>/, /<[0..9]>/); say 'Good' if $password ~~ /<[A..Z]>/ & /<[0..9]>/; my @values = (1 > 2, 3 == 4, 5 < 6); say 'Only one is true' if one(@values); my @numbers = (1, 0, 2, 5, 17); say 'No negative numbers' if none(@numbers) < 0;
  36. 45/73 Feed Operator • Shows the flow of data more

    clearly • So constructs like this: can be replaced with: or the other way around: @data ==> grep(* > 0) ==> unique() ==> sort() ==> @result; @result = sort(unique(grep(* > 0, @data))); @result <== sort() <== unique() <== grep(* > 0) <== @data;
  37. 46/73 Method Chaining • Method calls can be chained •

    Another feature that benefits code readability • So the construct shown earlier: can be written this way: @result = @data.grep(* > 0).unique.sort; @result = sort(unique(grep(* > 0, @data)));
  38. 47/73 Meta Operators • Reduction meta operator ([?]) applies any

    infix operator to all elements of a list: • Zip meta operator (Z?) applies an operator to successive pairs of items from two lists: my @numbers = (1, 2, 3, 4, 5); say "Sum: " ~ [+] @numbers; # Sum: 15 say "Product: " ~ [*] @numbers; # Product: 120 my @columns = <A B C>; my @rows = <1 2 3>; say @columns Z~ @rows; # (A1 B2 C3)
  39. 48/73 Meta Operators • Cross meta operator (X?) applies any

    infix operator to all pairs of items from two lists: • Reverse meta operator (R?) reverses the order of the arguments of an infix operator: my @columns = <A B C>; my @rows = <1 2 3>; say @columns X~ @rows; # (A1 A2 A3 B1 B2 B3 C1 C2 C3) say 5 - 3; # 2 say 5 R- 3; # -2
  40. 49/73 Meta Operators • Hyper operators (« and ») apply

    an operator to one or two lists and return a list of results: • If one list is shorter, it can be auto-expanded: • Can also be used with unary operations: say (10,20,30,40,50) »+« (2,4,6,8,10); # (12 24 36 48 60) say (10,20,30,40,50) »+» (2,4,6); # (12 24 36 42 54) say -« (10,20,30,40,50); # (-10 -20 -30 -40 -50)
  41. 51/73 Grammars • Grammars are regular expressions taken to the

    next level • A grammar is composed of tokens and rules • Example – a simple arithmetic expression rule: my token number { \d+ } my token op { < + - * / > } my rule expression { <number> <op> <number> } say(('42 - 13' ~~ /<expression>/).Bool); # True
  42. 52/73 Grammars my @s; grammar RPN { rule TOP {

    <expression>+ } rule expression { <number> { @s.push($/<number>); } | <op> { @s.push(@s.pop + @s.pop) if $/<op> eq '+'; @s.push(@s.pop * @s.pop) if $/<op> eq '*'; } } token op { < + * > } token number { \d+ } } RPN.parse(@*ARGS.shift); # '2 3 + 4 *' say @s[0]; # 20
  43. 54/73 Concurrency et al. • The language is designed to

    support concurrency and asynchronous programming • Built-in features include threads, promises, supplies, and channels • This allows for reactive and event-driven programming in Perl 6
  44. 55/73 Data Parallelism • The race and hyper methods iterate

    over data structures in parallel • So the grep line in this fragment of code: can be replaced with either of these: my @numbers = (1..100000); my @primes = @numbers.grep(*.is-prime); @primes = @numbers.hyper.grep(*.is-prime); @primes = @numbers.race.grep(*.is-prime);
  45. 56/73 Data Parallelism • The difference is that hyper preserves

    the order of elements, while race does not • The batch size and degree of parallelism (i.e., the number of workers) can be set explicitly: @numbers.race(batch => 32, degree => 4).grep(*.is-prime);
  46. 57/73 Promises • For asynchronously executing code and waiting for

    results • Implemented by means of the Promise class: my $promise = Promise.new; say $promise.status; # Planned $promise.keep('As promised'); say $promise.status; # Kept say $promise.result; # As promised
  47. 58/73 Promises • Starting a promise with a piece of

    code and awaiting its result: my @numbers = 1..100000; my $promise = start grep *.is-prime, @numbers; say "Doing something else"; my @primes = await $promise; say @primes.elems; # 9592
  48. 60/73 Unicode Support • As seen with the hyper operators

    (« and ») , Perl 6 embraces the use of Unicode in program code • Unicode characters can be used in identifiers • π, τ are built-in terms in Perl 6: sub circumference(Numeric $r) { τ * $r }
  49. 61/73 Unicode Support • Unicode character as a subroutine name:

    • Unicode data support is exceptionally good: sub Σ(*@elements) { [+] @elements } say Σ(1, 2, 3); # 6 say 'α'.succ; # β say 'Viel Spaß!'.uc; # VIEL SPASS! say 'Yes' if 'foobar' ~~ /foo.bar/; # Yes
  50. 63/73 Modules • There's no Perl 6 equivalent of Perl's

    glorious CPAN (yet) • A list of existing modules (mostly hosted on GitHub) is published at https://modules.perl6.org/ • Can be installed with the Panda utility (https://github.com/tadzik/panda/)
  51. 64/73 Modules • The Inline::Perl5 module allows using many Perl

    5 modules in Perl 6 programs • Even complex modules, such as DBI (database access interface), work • Usage is as simple as: use Inline::Perl5; use DBI:from<Perl5>; say DBI.available_drivers; # [DBM ExampleP File ...
  52. 66/73 Oneliners • Print all lines of a text file

    that exceed 80 characters: • Print a sum of comma-separated numbers • Fibonacci sequence (first n=10 elements): $ perl6 -e 'say((1, 1, * + * ... *)[^@*ARGS[0]])' 10 $ perl6 -ne '.print if .chars > 80' filename $ echo '1,2,3.14,4,0' | perl6 -ne 'say [+] .split(",")' $ perl6 -ne '.print if .chars > 80' filename $ perl6 -ne '.print if .chars > 80' filename
  53. 68/73 But Wait! There's More! • This presentation only shows

    some of all the interesting features of Perl 6 • (15 years is a long time, after all) • So go forth and explore!
  54. 69/73 Sources and Resources • Perl 6 Home Site (http://perl6.org/)

    • Perl 6 Docs (https://doc.perl6.org/) • Perl 6 Design Documents (http://design.perl6.org/) • Perl 6 Introduction (http://perl6intro.com/) • Perl 6 Advent Calendar (https://perl6advent.wordpress.com/)
  55. 71/73 Want to Take Perl 6 for a Spin? •

    Your best (easiest) option is Rakudobrew • Similar to what Perlbrew is for Perl 5, and virtualenv for Python • Installation is as simple as: git clone https://github.com/tadzik/rakudobrew ~/.rakudobrew export PATH=~/.rakudobrew/bin:$PATH rakudobrew init