diff --git a/perl6.html.markdown b/perl6.html.markdown index 92219708..fca863af 100644 --- a/perl6.html.markdown +++ b/perl6.html.markdown @@ -7,24 +7,29 @@ contributors: - ["Nami-Doc", "http://github.com/Nami-Doc"] --- -Perl 6 is a highly capable, feature-rich programming language made for the upcoming hundred years. +Perl 6 is a highly capable, feature-rich programming language made for the +upcoming hundred years. -Perl 6 runs on [the Parrot VM](http://parrot.org/), the JVM and [the MoarVM](http://moarvm.com). +Perl 6 runs on [the Parrot VM](http://parrot.org/), the JVM +and [the MoarVM](http://moarvm.com). + +Meta-note : the triple pound signs are here to denote headlines, +double paragraphs, and single notes. -Meta-note : the triple pound signs are here to denote headlines, double paragraphs, single notes. `#=>` represents the output of a command. ```perl # Single line comment start with a pound #`( - Multiline comments use #` and a quoting construct. (), [], {}, 「」, etc, will work. + Multiline comments use #` and a quoting construct. + (), [], {}, 「」, etc, will work. ) ### Variables # In Perl 6, you declare a lexical variable using `my` -a +my $variable; # Perl 6 has 4 variable types : ## * Scalars. They represent a single value. They start with a `$` @@ -32,19 +37,22 @@ a my $str = 'String'; my $str2 = "String"; # double quotes allow for interpolation -# variable names can contain but not end with simple quotes and dashes, and can contain (and end with) underscores : +# variable names can contain but not end with simple quotes and dashes, +# and can contain (and end with) underscores : # my $weird'variable-name_ = 5; # works ! my $bool = True; # `True` and `False` are Perl 6's boolean my $inverse = !$bool; # You can invert a bool with the prefix `!` operator -my $forced-bool = so $str; # And you can use the prefix `so` operator which turns its operand into a Bool +my $forced-bool = so $str; # And you can use the prefix `so` operator + # which turns its operand into a Bool ## * Arrays. They represent multiple values. Their name start with `@`. my @array = 1, 2, 3; my @array = 'a', 'b', 'c'; # equivalent to : -my @array = ; # array of words, delimited by space. similar to perl5's qw, or Ruby's %w +my @array = ; # array of words, delimited by space. + # Similar to perl5's qw, or Ruby's %w. say @array[2]; # Array indices start at 0 -- This is the third element @@ -58,10 +66,12 @@ my %hash = 1 => 2, my %hash = autoquoted => "key", # keys *can* get auto-quoted "some other" => "value", # trailing commas are okay ; -my %hash = ; # you can also create a hash from an even-numbered array +my %hash = ; # you can also create a hash + # from an even-numbered array my %hash = key1 => 'value1', key2 => 'value2'; # same as this -# You can also use the "colon pair" syntax: (especially handy for named parameters that you'll see later) +# You can also use the "colon pair" syntax: +# (especially handy for named parameters that you'll see later) my %hash = :w(1), # equivalent to `w => 1` # this is useful for the `True` shortcut: :truey, # equivalent to `:truey(True)`, or `truey => True` @@ -70,33 +80,37 @@ my %hash = :w(1), # equivalent to `w => 1` ; say %hash{'key1'}; # You can use {} to get the value from a key -say %hash; # if it's a string, you can actually use <> +say %hash; # If it's a string, you can actually use <> + # (`{key1}` doesn't work, as Perl6 doesn't have barewords) -## * Subs (subroutines, or functions in most other languages). Stored in variable, they use `&` +## * Subs (subroutines, or functions in most other languages). +# Stored in variable, they use `&`. sub say-hello { say "Hello, world" } -sub say-hello-to(Str $name) { # you can provide the type of an argument - # and it'll be checked at compile-time +sub say-hello-to(Str $name) { # You can provide the type of an argument + # and it'll be checked at compile-time. say "Hello, $name !"; } -# since you can omit parenthesis to call a function with no arguments, -# you need "&" in the name to capture `say-hello` +# Since you can omit parenthesis to call a function with no arguments, +# you need "&" in the name to capture `say-hello`. my &s = &say-hello; -my &other-s = sub { say "anonymous function !" } +my &other-s = sub { say "Anonymous function !" } # A sub can have a "slurpy" parameter, or "doesn't-matter-how-many" -sub as-many($head, *@rest) { # the `*@` slurpy will basically "take everything else". - # Note: you can have parameters *before* (like here) a slurpy one, - # but not *after*. +sub as-many($head, *@rest) { # The `*@` slurpy will basically "take everything else". + # Note: you can have parameters *before* (like here) + # a slurpy one, but not *after*. say @rest.join(' / ') ~ " !"; } say as-many('Happy', 'Happy', 'Birthday'); #=> Happy / Birthday ! - # Note that the splat did not consume the parameter before. + # Note that the splat did not consume + # the parameter before. -## You can call a function with an array using the "argument list flattening" operator `|` -# (it's not actually the only feature of the operator, but it's one of them) +## You can call a function with an array using the +# "argument list flattening" operator `|` +# (it's not actually the only role of this operator, but it's one of them) sub concat3($a, $b, $c) { say "$a, $b, $c"; } @@ -105,7 +119,8 @@ concat3(|@array); #=> a, b, c ## It can also have optional arguments: sub with-optional($arg?) { # the "?" marks the argument optional - say "I might return `(Any)` if I don't have an argument passed, or I'll return my argument"; + say "I might return `(Any)` if I don't have an argument passed, + or I'll return my argument"; $arg; } with-optional; # returns Any @@ -132,14 +147,15 @@ with-named(1, named => 6); #=> 7 with-named(2, :named(5)); #=> 7 with-named(3, :4named); #=> 7 - # (special colon pair syntax for numbers, mainly useful for `:2nd` etc) + # (special colon pair syntax for numbers, + # to be used with s// and such, see later) with-named(3); # warns, because we tried to use the undefined $named in a `+`: # by default, named arguments are *optional* # To make a named argument mandatory, you can use `?`'s inverse, `!` sub with-mandatory-named(:$str!) { - say "$named !"; + say "$str !"; } with-mandatory-named(str => "My String"); #=> My String ! with-mandatory-named; # run time error: "Required named parameter not passed" @@ -171,9 +187,10 @@ named-def(def => 15); #=> 15 ### Containers # In Perl 6, values are actually stored in "containers". -# The assignment operator asks the container on the left to store the value on its right. -# When passed around, containers are marked as immutable. Which means that, in a function, -# you'll get an error if you try to mutate one of your arguments. +# The assignment operator asks the container on the left to store the value on +# its right. When passed around, containers are marked as immutable. +# Which means that, in a function, you'll get an error if you try to +# mutate one of your arguments. # If you really need to, you can ask for a mutable container using `is rw` : sub mutate($n is rw) { $n++; @@ -185,7 +202,8 @@ sub mutate($n is rw) { # A sub itself returns a container, which means it can be marked as rw : my $x = 42; sub mod() is rw { $x } -mod() = 52; # in this case, the parentheses are mandatory (else Perl 6 thinks it's a "term") +mod() = 52; # in this case, the parentheses are mandatory + # (else Perl 6 thinks `mod` is a "term") say $x; #=> 52 @@ -197,9 +215,10 @@ say $x; #=> 52 ## Conditionals # - `if` -# Before talking about `if`, we need to know which values are "Truthy" (represent True), -# and which are "Falsey" (or "Falsy") -- meaning they represent False. -# Only these values are Falsey: (), 0, "0", Nil, A type, and of course False itself. +# Before talking about `if`, we need to know which values are "Truthy" +# (represent True), and which are "Falsey" (or "Falsy") -- represent False. +# Only these values are Falsey: (), 0, "0", Nil, A type (like `Str` or `Int`), +# and of course False itself. # Every other value is Truthy. if True { say "It's true !"; @@ -217,18 +236,18 @@ say "Quite truthy" if True; # - Ternary conditional, "?? !!" (like `x ? y : z` in some other languages) my $a = $condition ?? $value-if-true !! $value-if-false; -# - `given`-`when` looks like other languages `switch`, but it's much more powerful thanks to smart matching, -# and thanks to Perl 6's "topic variable", $_. +# - `given`-`when` looks like other languages `switch`, but much more +# powerful thanks to smart matching and thanks to Perl 6's "topic variable", $_. # This variable contains the default argument of a block, # a loop's current iteration (unless explicitly named), etc. -# Given simply puts its argument into `$_` (like a block would do), -# and `when` uses it using the "smart matching" operator. -# Since other Perl 6 constructs use this variable (as said before, like `for`, blocks, etc), -# this means the powerful `when` is not only applicable along with a `given`, -# but instead anywhere a `$_` exists. +# `given` simply puts its argument into `$_` (like a block would do), +# and `when` compares it using the "smart matching" (`~~`) operator. +# Since other Perl 6 constructs use this variable (as said before, like `for`, +# blocks, etc), this means the powerful `when` is not only applicable along with +# a `given`, but instead anywhere a `$_` exists. given "foo bar" { - when /foo/ { # you'll read about the smart-matching operator below -- just know `when` uses it - # this is equivalent to `if $_ ~~ /foo/` + when /foo/ { # You'll read about the smart-matching operator below -- just know `when` uses it. + # This is equivalent to `if $_ ~~ /foo/`. say "Yay !"; } when $_.chars > 50 { # smart matching anything with True (`$a ~~ True`) is True, @@ -242,15 +261,17 @@ given "foo bar" { ## Looping constructs -# - `loop` is an infinite loop if you don't pass it arguments, but can also be a c-style `for` : +# - `loop` is an infinite loop if you don't pass it arguments, +# but can also be a c-style `for` : loop { say "This is an infinite loop !"; last; # last breaks out of the loop, like the `break` keyword in other languages } loop (my $i = 0; $i < 5; $i++) { - next if $i == 3; # `next` skips to the next iteration, like `continue` in other languages. - # Notice that you can also use postfix conditionals, loops, etc. + next if $i == 3; # `next` skips to the next iteration, like `continue` + # in other languages. Note that you can also use postfix conditionals, + # loops, etc. say "This is a C-style for loop !"; } @@ -270,9 +291,10 @@ for @array { } for @array { - next if $_ == 3; # you can skip to the next iteration (like `continue` in C-like languages) - redo if $_ == 4; # you can re-do the iteration, keeping the same topic variable (`$_`) - last if $_ == 5; # you can also break out of a loop (like `break` in C-like languages) + # You can... + next if $_ == 3; # Skip to the next iteration (like `continue` in C-like languages). + redo if $_ == 4; # Re-do the iteration, keeping the same topic variable (`$_`). + last if $_ == 5; # Or break out of a loop (like `break` in C-like languages). } # Note - the "lambda" `->` syntax isn't reserved to `for` : @@ -283,8 +305,8 @@ if long-computation() -> $result { ### Operators ## Since Perl languages are very much operator-based languages -## Perl 6 operators are actually just funny-looking subroutines, in syntactic categories, -## like infix:<+> (addition) or prefix: (bool not) +## Perl 6 operators are actually just funny-looking subroutines, in syntactic +## categories, like infix:<+> (addition) or prefix: (bool not). ## The categories are : # - "prefix" : before (like `!` in `!True`). @@ -312,12 +334,14 @@ if long-computation() -> $result { (1, 2) eqv (1, 3); # - `~~` is smart matching -# for a complete combinations list, use this table : http://perlcabal.org/syn/S03.html#Smart_matching +# For a complete list of combinations, use this table : http://perlcabal.org/syn/S03.html#Smart_matching 'a' ~~ /a/; # true if matches regexp 'key' ~~ %hash; # true if key exists in hash -$arg ~~ &bool-returning-function; # true if the function, passed `$arg` as an argument, returns True -1 ~~ Int; # "is of type" -1 ~~ True; # smart-matching against a boolean always returns that boolean (and will warn). +$arg ~~ &bool-returning-function; # `True` if the function, passed `$arg` + # as an argument, returns `True`. +1 ~~ Int; # "has type" (check superclasses and roles) +1 ~~ True; # smart-matching against a boolean always returns that boolean + # (and will warn). # - `===` is value identity and uses `.WHICH` on the objects to compare them # - `=:=` is container identity and uses `VAR()` on the objects to compare them @@ -330,38 +354,44 @@ $arg ~~ &bool-returning-function; # true if the function, passed `$arg` as an ar 3 .. 7; # 3 to 7, both included # `^` on either side them exclusive on that side : 3 ^..^ 7; # 3 to 7, not included (basically `4 .. 6`) -# this also works as a shortcut for `0..^N` +# This also works as a shortcut for `0..^N`: ^10; # means 0..^10 -# This also allows us to demonstrate that Perl 6 has lazy arrays, using the Whatever Star : +# This also allows us to demonstrate that Perl 6 has lazy arrays, +# using the Whatever Star: my @array = 1..*; # 1 to Infinite ! -say @array[^10]; # you can pass arrays as subscripts and it'll return an array of results - # this will print "1 2 3 4 5 6 7 8 9 10" (and not run out of memory !) -# Note : when reading an infinite list, Perl 6 will "reify" the elements it needs, then keep them in memory -# They won't be calculated more than once. +say @array[^10]; # you can pass arrays as subscripts and it'll return + # an array of results. This will print + # "1 2 3 4 5 6 7 8 9 10" (and not run out of memory !) +# Note : when reading an infinite list, Perl 6 will "reify" the elements +# it needs, then keep them in memory. They won't be calculated more than once. -# Warning, though: if you try this example in the REPL and juste put `1..*`, -# Perl 6 will be forced to try and evaluate the whole array (to print it), -# so you'll end with an infinite loop. +# Warning, though: if you try this example in the REPL and just put `1..*`, +# Perl 6 will be forced to try and evaluate the whole array (to print it), +# so you'll end with an infinite loop. ## * And, Or 3 && 4; # 4, which is Truthy. Calls `.Bool` on `4` and gets `True`. 0 || False; # False. Calls `.Bool` on `0` ## * Short-circuit (and tight) versions of the above -$a && $b && $c; # returns the first argument that evaluates to False, or the last argument +$a && $b && $c; # Returns the first argument that evaluates to False, + # or the last argument. $a || $b; -# And because you're going to want them, you also have composed assignment operators: +# And because you're going to want them, +# you also have composed assignment operators: $a *= 2; # multiply and assignment $b %%= 5; # divisible by and assignment -$c .= say; # method call and assignment +@array .= sort; # calls the `sort` method and assigns the result back ### More on subs ! -# As we said before, Perl 6 has *really* powerful subs. -# We're going to see a few more key concepts that make them better than in any other language :-). +# As we said before, Perl 6 has *really* powerful subs. We're going to see +# a few more key concepts that make them better than in any other language :-). -## Unpacking ! It's the ability to "extract" arrays and keys. It'll work in `my`s and parameters. +## Unpacking ! +# It's the ability to "extract" arrays and keys. +# It'll work in `my`s and in parameter lists. my ($a, $b) = 1, 2; say $a; #=> 1 my ($, $, $c) = 1, 2, 3; # keep the non-interesting anonymous @@ -377,14 +407,17 @@ sub foo(@array [$fst, $snd]) { foo(@tail); #=> My first is 2, my second is 3 ! All in all, I'm 2 3 -# If you're not using the array itself, you can also keep it anonymous, much like a scalar: +# If you're not using the array itself, you can also keep it anonymous, +# much like a scalar: sub first-of-array(@ [$fst]) { $fst } first-of-array(@small); #=> 1 -first-of-array(@tail); # errors with "Too many positional parameters passed" (the array is too big) +first-of-array(@tail); # Throws an error "Too many positional parameters passed" + # (which means the array is too big). # You can also use a slurp ... sub slurp-in-array(@ [$fst, *@rest]) { # you could decide to keep `*@rest` anonymous - say $fst + @rest.elems; + say $fst + @rest.elems; # `.elems` returns a list's length. + # Here, `@rest` is `(3,)`, since `$fst` holds the `2`. } slurp-in-array(@tail); #=> 3 @@ -403,18 +436,21 @@ sub key-of(% (:value($val), :qua($qua))) { } # Then call it with a hash: (you need to keep the brackets for it to be a hash) -key-of({value => 1}); +key-of({value => 'foo', qua => 1}); #key-of(%hash); # the same (for an equivalent `%hash`) -## The last expression of a sub is returned automatically (though you may use the `return` keyword, of course): +## The last expression of a sub is returned automatically +# (though you may use the `return` keyword, of course): sub next-index($n) { $n + 1; } my $new-n = next-index(3); # $new-n is now 4 -# This is true for everything, except for the looping constructs (due to performance reasons): -# there's no purpose in building a list if we're just going to discard all the results. -# If you still want to build one, you can use the `do` prefix: (or the `gather` prefix, which we'll see later) +# This is true for everything, except for the looping constructs +# (due to performance reasons): there's reason to build a list +# if we're just going to discard all the results. +# If you still want to build one, you can use the `do` statement prefix: +# (or the `gather` prefix, which we'll see later) sub list-of($n) { do for ^$n { # note the use of the range-to prefix operator `^` (`0..^N`) $_ # current loop iteration @@ -424,15 +460,16 @@ my @list3 = list-of(3); #=> (0, 1, 2) ## You can create a lambda with `-> {}` ("pointy block") or `{}` ("block") my &lambda = -> $argument { "The argument passed to this lambda is $argument" } -# `-> {}` and `{}` are pretty much the same thing, except that the former can take arguments, -# and that the latter can be mistaken as a hash by the parser. +# `-> {}` and `{}` are pretty much the same thing, except that the former can +# take arguments, and that the latter can be mistaken as a hash by the parser. # We can, for example, add 3 to each value of an array using map: my @arrayplus3 = map({ $_ + 3 }, @array); # $_ is the implicit argument -# a sub (`sub {}`) has different semantics than a block (`{}` or `-> {}`): -# a block doesn't have a "function context" (though it can have arguments), which means that if you -# return from it, you're going to return from the parent function, compare: +# A sub (`sub {}`) has different semantics than a block (`{}` or `-> {}`): +# A block doesn't have a "function context" (though it can have arguments), +# which means that if you return from it, +# you're going to return from the parent function. Compare: sub is-in(@array, $elem) { # this will `return` out of the `is-in` sub # once the condition evaluated to True, the loop won't be run anymore @@ -441,7 +478,7 @@ sub is-in(@array, $elem) { sub truthy-array(@array) { # this will produce an array of `True` and `False`: # (you can also say `anon sub` for "anonymous subroutine") - map(sub { if $_ { return True } else { return False } }, @array); + map(sub ($i) { if $i { return True } else { return False } }, @array); # ^ the `return` only returns from the anonymous `sub` } @@ -454,15 +491,17 @@ say (*/2)(4); #=> 2 say ((*+3)/5)(5); #=> 1.6 # works even in parens ! -# but if you need to have more than one argument (`$_`) in a block (without wanting to resort to `-> {}`), +# But if you need to have more than one argument (`$_`) +# in a block (without wanting to resort to `-> {}`), # you can also use the implicit argument syntax, `$^` : map({ $^a + $^b + 3 }, @array); # same as the above -# Note : those are sorted lexicographically. `{ $^b / $^a }` is like `-> $a, $b { $b / $a }` +# Note : those are sorted lexicographically. +# `{ $^b / $^a }` is like `-> $a, $b { $b / $a }` ## Multiple Dispatch -# Perl 6 can decide which variant of a `sub` to call based on the type of the arguments, -# or on arbitrary preconditions, like with a type or a `where`: +# Perl 6 can decide which variant of a `sub` to call based on the type of the +# arguments, or on arbitrary preconditions, like with a type or a `where`: # with types multi sub sayit(Int $n) { # note the `multi` keyword here @@ -472,21 +511,25 @@ multi sayit(Str $s) } # the `sub` is the default say "String: $s"; } sayit("foo"); # prints "String: foo" -sayit(True); # fails at *compile time* with "calling 'sayit' will never work with arguments of types ..." +sayit(True); # fails at *compile time* with + # "calling 'sayit' will never work with arguments of types ..." # with arbitrary precondition: multi is-big(Int $n where * > 50) { "Yes !" } # using a closure -multi is-big(Int $ where 10..50) { "Quite." } # this uses smart-matching (could use a regexp, etc) +multi is-big(Int $ where 10..50) { "Quite." } # Using smart-matching + # (could use a regexp, etc) multi is-big(Int $) { "No" } -# you can also name these checks, by creating "subsets": +# You can also name these checks, by creating "subsets": subset Even of Int where * %% 2; -multi odd-or-even(Even) { "Even" } # the main case using the type. We don't name the argument +multi odd-or-even(Even) { "Even" } # The main case using the type. + # We don't name the argument. multi odd-or-even($) { "Odd" } # "else" # You can even dispatch based on a positional's argument presence ! -multi with-or-without-you(:$with!) { # make it mandatory to be able to dispatch against it +multi with-or-without-you(:$with!) { # You need make it mandatory to + # be able to dispatch against it. say "I can live ! Actually, I can't."; } multi with-or-without-you { @@ -494,17 +537,21 @@ multi with-or-without-you { } # This is very, very useful for many purposes, like `MAIN` subs (covered later), # and even the language itself is using it in several places. -# `is`, for example, is actually a `multi sub` named `trait_mod:`, and it works off that. -# `is rw`, for example, is a dispatch to a function with this signature: +# +# - `is`, for example, is actually a `multi sub` named `trait_mod:`, +# and it works off that. +# - `is rw`, is simply a dispatch to a function with this signature: # sub trait_mod:(Routine $r, :$rw!) {} -# (commented because running this would probably lead to some very surprising side-effects !) +# +# (commented because running this would be a terrible idea !) ### Scoping -# In Perl 6, contrarily to many scripting languages (Python, Ruby, PHP, for example), -# you are to declare your variables before using them. You already saw it, with `my`. -# (there are other declarator keywords, like `our`, `has` and `state`, but we'll talk about them later) -# This is called "lexical scoping", where in inner blocks, you can access variables from outer blocks. +# In Perl 6, contrarily to many scripting languages (like Python, Ruby, PHP), +# you are to declare your variables before using them. You know `my`. +# (there are other declarators, `our`, `state`, ..., which we'll see later). +# This is called "lexical scoping", where in inner blocks, +# you can access variables from outer blocks. my $foo = 'Foo'; sub foo { my $bar = 'Bar'; @@ -516,36 +563,39 @@ sub foo { foo()(); #=> 'Foo Bar' # As you can see, `$foo` and `$bar` were captured. -# But if we were to try and use `$bar` outside of `foo`, the variable would be undefined. -# (and you'd get a compile time error) +# But if we were to try and use `$bar` outside of `foo`, +# the variable would be undefined (and you'd get a compile time error). # Perl 6 has another kind of scope : dynamic scope. # They use the twigil (composed sigil) `*` to mark dynamically-scoped variables: my $*a = 1; -# Dyamically-scoped variables depend on the current call stack, instead of the current block stack. +# Dyamically-scoped variables depend on the current call stack, +# instead of the current block depth. sub foo { my $*foo = 1; bar(); # call `bar` in-place } sub bar { say $*foo; # Perl 6 will look into the call stack instead, and find `foo`'s `$*a`, - # even though the blocks aren't nested (they're call-nested). + # even though the blocks aren't nested (they're call-nested). #=> 1 } ### Object Model ## Perl 6 has a quite comprehensive object model -## You declare a class with the keyword `class`, fields with `has`, methods with `method`. -## In Perl 6, every field is private, and named `$!attr`, but if you declare it with `$.`, -## you get a public (immutable) accessor along with it. +# You declare a class with the keyword `class`, fields with `has`, +# methods with `method`. Every field to private, and is named `$!attr`, +# but you have `$.` to get a public (immutable) accessor along with it. +# (using `$.` is like using `$!` plus a `method` with the same name) # (Perl 6's object model ("SixModel") is very flexible, and allows you to dynamically add methods, # change semantics, etc -- This will not be covered here, and you should refer to the Synopsis) class A { - has $.field; # `$.field` is immutable. Use `$!field` from inside the class to modify it. - has $.other-field is rw; # You can, however, mark a public field as being read/write. + has $.field; # `$.field` is immutable. + # From inside the class, use `$!field` to modify it. + has $.other-field is rw; # You can obviously mark a public field `rw`. has Int $!private-field = 10; method get-value { @@ -556,7 +606,7 @@ class A { # $.field = $n; # As stated before, you can't use the `$.` immutable version. $!field = $n; # This works, because `$!` is always mutable. - $.other-field = 5; # This works, because `$.other-field` was declared `rw` (mutable). + $.other-field = 5; # This works, because `$.other-field` is `rw`. } method !private-method { @@ -565,13 +615,15 @@ class A { }; # Create a new instance of A with $.field set to 5 : -# note : you can't set private-field from here (more later on) +# Note: you can't set private-field from here (more later on). my $a = A.new(field => 5); $a.get-value; #=> 18 #$a.field = 5; # This fails, because the `has $.field` is immutable -$a.other-field = 10; # This, however, works, because the public field is mutable (`rw`). +$a.other-field = 10; # This, however, works, because the public field + # is mutable (`rw`). -## Perl 6 also has inheritance (along with multiple inheritance ... Considered a misfeature by many) +## Perl 6 also has inheritance (along with multiple inheritance) +# (though considered a misfeature by many) class A { has $.val; @@ -591,12 +643,14 @@ class B is A { # inheritance uses `is` method bar { $.val * 10 } # this shadows A's `bar` } -my B $b .= new(val => 5); # When you use `my T $var`, `$var` starts off with `T` itself in it, - # so you can call `new` on it. - # (`.=` is just the compound operator composed of the dot-call and of the assignment operator - # `$a .= b` is the same as `$a = $a.b`) - # Also note that `BUILD` (the method called inside `new`) will set parent properties too, - # so you can pass `val => 5` +# When you use `my T $var`, `$var` starts off with `T` itself in it, +# so you can call `new` on it. +# (`.=` is just the dot-call and the assignment operator: +# `$a .= b` is the same as `$a = $a.b`) +# Also note that `BUILD` (the method called inside `new`) +# will set parent properties too, so you can pass `val => 5`. +my B $b .= new(val => 5); + # $b.not-inherited; # This won't work, for reasons explained above $b.foo; # prints 5 $b.bar; #=> 50, since it calls B's `bar` @@ -613,27 +667,30 @@ role PrintableVal { class Item does PrintableVal { has $.val; - # When `does`-ed, a `role` literally "mixes in" the class : - # the methods and fields are put together, which means a class can access - # the private fields/methods of its roles (but not the inverse !) : + # When `does`-ed, a `role` literally "mixes in" the class: + # the methods and fields are put together, which means a class can access + # the private fields/methods of its roles (but not the inverse !): method access { say $!counter++; } - # However, this : + # However, this: # method print {} - # is an error, since the compiler wouldn't know which `print` to use : - # contrarily to inheritance, methods mixed in can't be shadowed - they're put at the same "level" + # is ONLY valid when `print` isn't a `multi` with the same dispatch. + # (this means a parent class can shadow a child class's `multi print() {}`, + # but it's an error if a role does) - # NOTE: You can use a role as a class (with `is ROLE`). In this case, methods will be shadowed, - # since the compiler will consider `ROLE` to be a class + # NOTE: You can use a role as a class (with `is ROLE`). In this case, methods + # will be shadowed, since the compiler will consider `ROLE` to be a class. } ### Exceptions # Exceptions are built on top of classes, usually in the package `X` (like `X::IO`). -# Unlike many other languages, in Perl 6, you put the `CATCH` block *within* the block to `try`. -# By default, a `try` has a `CATCH` block that catches any exception (`CATCH { default {} }`). -# You can redefine it using `when`s (and `default`) to handle the exceptions you want: +# Unlike many other languages, in Perl 6, you put the `CATCH` block *within* the +# block to `try`. By default, a `try` has a `CATCH` block that catches +# any exception (`CATCH { default {} }`). +# You can redefine it using `when`s (and `default`) +# to handle the exceptions you want: try { open 'foo'; CATCH { @@ -649,17 +706,17 @@ die X::AdHoc.new(payload => 'Error !'); # TODO CONTROL ### Packages -# Packages are a way to reuse code. Packages are like "namespaces", and any element of the six model -# (`module`, `role`, `class`, `grammar`, `subset` and `enum`) are actually packages. -# (you can say that packages are the lowest common denomitor between them) -# Packages play a big part in a language, as Perl is well-known for CPAN, +# Packages are a way to reuse code. Packages are like "namespaces", and any +# element of the six model (`module`, `role`, `class`, `grammar`, `subset` +# and `enum`) are actually packages. (Packages are the lowest common denomitor) +# Packages play a big part in a language, especially as Perl is well-known for CPAN, # the Comprehensive Perl Archive Network. -# You usually don't use packages directly : you use `class Package::Name::Here;`, or if you -# only want to export variables/subs, you can use `module`: -module Hello::World { # bracketed form - # if `Hello` doesn't exist yet, it'll just be created as an "empty package stub" - # that can be redeclared as something else later. - # declarations here +# You usually don't use packages directly: you use `class Package::Name::Here;`, +# or if you only want to export variables/subs, you can use `module`: +module Hello::World { # Bracketed form + # If `Hello` doesn't exist yet, it'll just be a "stub", + # that can be redeclared as something else later. + # ... declarations here ... } module Parse::Text; # file-scoped form grammar Parse::Text::Grammar { # A grammar is a fine package, which you could `use` @@ -692,7 +749,8 @@ my $actions = JSON::Tiny::Actions.new; module Foo::Bar { our $n = 1; # note: you can't put a type constraint on an `our` variable our sub inc { - our sub available { # if you try to make scoped `sub`s `our` ... Better know what you're doing (Don't !). + our sub available { # If you try to make inner `sub`s `our`... + # Better know what you're doing (Don't !). say "Don't do that. Seriously. You'd get burned."; } my sub unavailable { # `my sub` is the default @@ -725,23 +783,24 @@ sub fixed-rand { fixed-rand for ^10; # will print the same number 10 times # Note, however, that they exist separately in different enclosing contexts. -# If you declare a function with a `state` within a loop, it'll re-create the variable -# for each iteration of loop. See: +# If you declare a function with a `state` within a loop, it'll re-create the +# variable for each iteration of the loop. See: for ^5 -> $a { sub foo { state $val = rand; # This will be a different value for every value of `$a` } for ^5 -> $b { - say foo; # This will print the same value 5 times, but only 5. Next iteration will re-run `rand` + say foo; # This will print the same value 5 times, but only 5. + # Next iteration will re-run `rand`. } } ### Phasers -# Phasers in Perl 6 are blocks that happen at determined points of time in your program -# When the program is compiled, when a for loop runs, when you leave a block, when -# an exception gets thrown ... (`CATCH` is actually a phaser !) +# Phasers in Perl 6 are blocks that happen at determined points of time in your +# program. When the program is compiled, when a for loop runs, when you leave a +# block, when an exception gets thrown ... (`CATCH` is actually a phaser !) # Some of them can be used for their return values, some of them can't # (those that can have a "[*]" in the beginning of their explanation text). # Let's have a look ! @@ -791,7 +850,7 @@ sub do-db-stuff { # Those act a bit like phasers: they affect the behavior of the following code. # Though, they run in-line with the executable code, so they're in lowercase. # (`try` and `start` are theoretically in that list, but explained somewhere else) -# Note: all of these (except start) don't need explicit brackets (`{` and `}`) for their block. +# Note: all of these (except start) don't need explicit brackets `{` and `}`. # - `do` (that you already saw) - runs a block or a statement as a term # You can't normally use a statement as a value (or "term"): @@ -848,8 +907,9 @@ say nilthingie.perl; #=> Nil ## Everybody loves operators ! Let's get more of them -## The precedence list can be found here : http://perlcabal.org/syn/S03.html#Operator_precedence -## But first, we need a little explanation about associativity : +# The precedence list can be found here: +# http://perlcabal.org/syn/S03.html#Operator_precedence +# But first, we need a little explanation about associativity: # * Binary operators: $a ! $b ! $c; # with a left-associative `!`, this is `($a ! $b) ! $c` @@ -864,8 +924,9 @@ $a ! $b ! $c; # with a list-associative `!`, this is `infix:<>` !$a! # with non-associative `!`, this is illegal ## Create your own operators ! -# Okay, you've been reading all of that, so I guess I should try to show you something exciting. -# I'll tell you a little secret (actually not): +# Okay, you've been reading all of that, so I guess I should try +# to show you something exciting. +# I'll tell you a little secret (or not-so-secret): # In Perl 6, all operators are actually just funny-looking subroutines. # You can declare an operator just like you declare a sub: @@ -906,36 +967,46 @@ sub circumfix:<[ ]>(Int $n) { say [5]; #=> 3125 # circumfix is around. Again, not whitespace. -sub postcircumfix:<{ }>(Str $s, Int $idx) { # post-circumfix is "after a term, around something" +sub postcircumfix:<{ }>(Str $s, Int $idx) { + # post-circumfix is + # "after a term, around something" $s.substr($idx, 1); } say "abc"{1}; #=> b # after the term `"abc"`, and around the index (1) # This really means a lot -- because everything in Perl 6 uses this. -# For example, to delete a key from a hash, you use the `:delete` adverb (named argument) +# For example, to delete a key from a hash, you use the `:delete` adverb +# (a simple named argument underneath): %h{$key}:delete; # equivalent to: -postcircumfix:<{ }>(%h, $key, :delete); -# It's *all* using the same building blocks! Syntactic categories (prefix infix ...), -# named arguments (adverbs), ..., used to build the language are available to you. +postcircumfix:<{ }>(%h, $key, :delete); # (you can call operators like that) +# It's *all* using the same building blocks! +# Syntactic categories (prefix infix ...), named arguments (adverbs), ..., +# - used to build the language - are available to you. -# (you are, obviously, recommended against making an operator out of *everything* -- -# with great power comes great responsibility) +# (you are, obviously, recommended against making an operator out of +# *everything* -- with great power comes great responsibility) ## Meta operators ! -# Oh boy, get ready. Get ready, because we're dwelving deep into the rabbit's hole, -# and you probably won't want to go back to other languages after reading that. +# Oh boy, get ready. Get ready, because we're dwelving deep +# into the rabbit's hole, and you probably won't want to go +# back to other languages after reading that. # (I'm guessing you don't want to already at that point). # Meta-operators, as their name suggests, are *composed* operators. # Basically, they're operators that apply another operator. ## * Reduce meta-operator -# It's a prefix meta-operator that takes a binary functions and one or many lists. -# If it doesn't get passed any argument, it either return a "default value" for this operator -# (a value that'd be non-meaningful if contained in a list) or `Any` if there's none. +# It's a prefix meta-operator that takes a binary functions and +# one or many lists. If it doesn't get passed any argument, +# it either return a "default value" for this operator +# (a value that wouldn't change the result if passed as one +# of the element of the list to be passed to the operator), +# or `Any` if there's none (examples below). +# # Otherwise, it pops an element from the list(s) one at a time, and applies the binary function # to the last result (or the list's first element) and the popped element. +# # To sum a list, you could use the reduce meta-operator with `+`, i.e.: say [+] 1, 2, 3; #=> 6 # equivalent to `(1+2)+3` @@ -943,18 +1014,20 @@ say [*] 1..5; #=> 120 # equivalent to `((((1*2)*3)*4)*5)`. # You can reduce with any operator, not just with mathematical ones. -# For example, you could reduce with `//` to get the first defined element of a list: +# For example, you could reduce with `//` to get +# the first defined element of a list: say [//] Nil, Any, False, 1, 5; #=> False # (Falsey, but still defined) # Default value examples: -say [*] (); #=> 1 -say [+] (); #=> 0 - # In both cases, they're results that, if they were contained in the lists, - # wouldn't have any impact on the final value (since N*1=N and N+0=N). +say [*] (); #=> 1 +say [+] (); #=> 0 + # In both cases, they're results that, were they in the lists, + # wouldn't have any impact on the final value + # (since N*1=N and N+0=N). say [//]; #=> (Any) - # There's no "default value" for `//` + # There's no "default value" for `//`. # You can also call it with a function you made up, using double brackets: sub add($a, $b) { $a + $b } @@ -980,23 +1053,31 @@ say [[&add]] 1, 2, 3; #=> 6 ## * Sequence operator # The sequence operator is one of Perl 6's most powerful features: -# it's composed of first, on the left, the list you want Perl 6 to deduce from (and might include a closure), -# and on the right, a value or the predicate for when to stop, or even Whatever for a lazy infinite list. +# it's composed of first, on the left, the list you want Perl 6 to deduce from +# (and might include a closure), and on the right, a value or the predicate +# that says when to stop (or Whatever for a lazy infinite list). my @list = 1, 2, 3 ... 10; # basic deducing -#my @list = 1, 3, 6 ... 10; # this throws you into an infinite loop, because Perl 6 can't figure out the end -my @list = 1, 2, 3 ...^ 10; # as with ranges, you can exclude the last element (when the predicate matches) -my @list = 1, 3, 9 ... * > 30; # you can use a predicate (with the Whatever Star, here) +#my @list = 1, 3, 6 ... 10; # this throws you into an infinite loop, + # because Perl 6 can't figure out the end +my @list = 1, 2, 3 ...^ 10; # as with ranges, you can exclude the last element + # (the iteration when the predicate matches). +my @list = 1, 3, 9 ... * > 30; # you can use a predicate + # (with the Whatever Star, here). my @list = 1, 3, 9 ... { $_ > 30 }; # (equivalent to the above) -my @fib = 1, 1, *+* ... *; # lazy infinite list of prime numbers, computed using a closure ! + +my @fib = 1, 1, *+* ... *; # lazy infinite list of prime numbers, + # computed using a closure! my @fib = 1, 1, -> $a, $b { $a + $b } ... *; # (equivalent to the above) say @fib[^10]; #=> 1 1 2 3 5 8 13 21 34 55 # (using a range as the index) # Note : as for ranges, once reified, elements aren't re-calculated. -# That's why `@primes[^100]` will take a long time the first time you print it, then be instant +# That's why `@primes[^100]` will take a long time the first time you print +# it, then be instant. ## * Sort comparison -# They return one value of the `Order` enum : `Less`, `Same` and `More` (which numerify to -1, 0 or +1). +# They return one value of the `Order` enum : `Less`, `Same` and `More` +# (which numerify to -1, 0 or +1). 1 <=> 4; # sort comparison for numerics 'a' leg 'b'; # sort comparison for string $obj eqv $obj2; # sort comparison using eqv semantics @@ -1014,14 +1095,17 @@ say Any // Nil // 0 // 5; #=> 5 say True ^^ False; #=> True ## * Flip Flop -# The flip flop operators (`ff` and `fff`, equivalent to Perl 5/Ruby's `..` and `...`). +# The flip flop operators (`ff` and `fff`, equivalent to P5's `..`/`...`). # are operators that take two predicates to test: -# They are `False` until their left side returns `True`, then are `True` until their right side returns `True`. -# Like for ranges, you can exclude the iteration when it became `True`/`False` by using `^` on either side. +# They are `False` until their left side returns `True`, then are `True` until +# their right side returns `True`. +# Like for ranges, you can exclude the iteration when it became `True`/`False` +# by using `^` on either side. # Let's start with an example : for { # by default, `ff`/`fff` smart-match (`~~`) against `$_`: - if 'met' ^ff 'meet' { # won't enter the if for "met" (explained in details below). + if 'met' ^ff 'meet' { # Won't enter the if for "met" + # (explained in details below). .say } @@ -1031,20 +1115,24 @@ for { } # This will print "young hero we shall meet" (excluding "met"): # the flip-flop will start returning `True` when it first encounters "met" -# (but will still return `False` for "met" itself, due to the leading `^` on `ff`), -# until it sees "meet", which is when it'll start returning `False`. +# (but will still return `False` for "met" itself, due to the leading `^` +# on `ff`), until it sees "meet", which is when it'll start returning `False`. # The difference between `ff` (awk-style) and `fff` (sed-style) is that -# `ff` will test its right side just as its left side changes to `True`, -# and can get back to `False` right away (*except* it'll be `True` for the iteration that matched) -# while `fff` will wait for the next iteration to try its right side, once its left side changed: +# `ff` will test its right side right when its left side changes to `True`, +# and can get back to `False` right away +# (*except* it'll be `True` for the iteration that matched) - +# While `fff` will wait for the next iteration to +# try its right side, once its left side changed: .say if 'B' ff 'B' for ; #=> B B - # because the right-hand-side was tested directly (and returned `True`). + # because the right-hand-side was tested + # directly (and returned `True`). # "B"s are still printed since it matched that time - # (it just went back to `False` right away) + # (it just went back to `False` right away). .say if 'B' fff 'B' for ; #=> B C B - # because the right-hand-side wasn't tested until `$_` became "C" - # (and thus did not match directly). + # because the right-hand-side wasn't tested until + # `$_` became "C" + # (and thus did not match instantly). # A flip-flop can change state as many times as needed: for { @@ -1054,12 +1142,15 @@ for 50 ff *; # Once the flip-flop reaches a number greater than 50, it'll never go back to `False` +for (1, 3, 60, 3, 40, 60) { # Note: the parenthesis are superfluous here + # (sometimes called "superstitious parentheses") + .say if $_ > 50 ff *; # Once the flip-flop reaches a number greater than 50, + # it'll never go back to `False` #=> 60 3 40 60 } -# You can also use this property to create an `If` that'll not execute the first time : +# You can also use this property to create an `If` +# that'll not go through the first time : for { .say if * ^ff *; # the flip-flop is `True` and never goes back to `False`, # but the `^` makes it *not run* on the first iteration @@ -1072,28 +1163,33 @@ for { # Well, now that you know a good deal of Perl 6 already, we can get started. # First off, you'll have to forget about "PCRE regexps" (perl-compatible regexps). # -# IMPORTANT: You may feel like you already know these because you know PCRE. You'd be wrong. -# Some things are the same (like `?`, `+`, and `*`), but sometimes the semantics change (`|`). +# IMPORTANT: Don't skip them because you know PCRE. They're different. +# Some things are the same (like `?`, `+`, and `*`), +# but sometimes the semantics change (`|`). # Make sure you read carefully, because you might trip over a new behavior. # -# Perl 6 has a looot of features related to RegExps. After all, Rakudo parses itself. -# We're first going to look at the syntax itself, then talk about grammars (PEG-like), -# differences between the `token`, `regex` and `rule` keywords, and some more. +# Perl 6 has many features related to RegExps. After all, Rakudo parses itself. +# We're first going to look at the syntax itself, +# then talk about grammars (PEG-like), differences between +# `token`, `regex` and `rule` declarators, and some more. # Side note: you still have access to PCRE regexps using the `:P5` modifier. # (we won't be discussing this in this tutorial, however) # # In essence, Perl 6 natively implements PEG ("Parsing Expression Grammars"). -# The pecking order for ambiguous parses is determined by a multi-level tie-breaking test: +# The pecking order for ambiguous parses is determined by a multi-level +# tie-breaking test: # - Longest token matching. `foo\s+` beats `foo` (by 2 or more positions) # - Longest literal prefix. `food\w*` beats `foo\w*` (by 1) -# - Declaration from most-derived to less derived grammars (grammars are actually classes) +# - Declaration from most-derived to less derived grammars +# (grammars are actually classes) # - Earliest declaration wins say so 'a' ~~ /a/; #=> True say so 'a' ~~ / a /; # More readable with some spaces! -# In all our examples, we're going to use the smart-matching operator against a regexp. -# We're converting the result using `so`, but in fact, it's returning a `Match` object. -# They know how to respond to list indexing, hash indexing (and return the matched string). +# In all our examples, we're going to use the smart-matching operator against +# a regexp. We're converting the result using `so`, but in fact, it's +# returning a `Match` object. They know how to respond to list indexing, +# hash indexing, and return the matched string. # The results of the match are also available as `$/` (implicitly lexically-scoped). # You can also use the capture variables (`$0`, `$1`, ... - starting at 0, not 1 !). # @@ -1101,8 +1197,8 @@ say so 'a' ~~ / a /; # More readable with some spaces! # (meaning the regexp can be matched with just one char of the string), # we're going to explain later how you can do it. -# In Perl 6, you can have any alphanumeric as a literal, everything else has to be escaped, -# using a backslash or quotes. +# In Perl 6, you can have any alphanumeric as a literal, +# everything else has to be escaped, using a backslash or quotes. say so 'a|b' ~~ / a '|' b /; # `True`. Wouln't mean the same if `|` wasn't escaped say so 'a|b' ~~ / a \| b /; # `True`. Another way to escape it. @@ -1140,7 +1236,8 @@ so 'abbbbc' ~~ / a b* c /; # `True` so 'aec' ~~ / a b* c /; # `False`. "b"(s) are optional, but can't be something else. # - `**` - "Quantify It Yourself". -# If you squint hard enough, you might understand the why exponentation means quantity. +# If you squint hard enough, you might understand +# why exponentation is used for quantity. so 'abc' ~~ / a b ** 1 c /; # `True` (exactly one time) so 'abc' ~~ / a b ** 1..3 c /; # `True` (one to three times) so 'abbbc' ~~ / a b ** 1..3 c /; # `True` @@ -1151,11 +1248,12 @@ so 'abbbbbbc' ~~ / a b ** 3..* c /; # `True` (infinite ranges are okay) # Group: you can group parts of your regexp with `[]`. # These groups are *not* captured (like PCRE's `(?:)`). so 'abc' ~~ / a [ b ] c /; # `True`. The grouping does pretty much nothing -so 'fooABCABCbar' ~~ / foo [ A B C ] + bar /; # `True`. - # We match the "abc" 1 or more time. - # (the `+` was applied to the group) +so 'fooABCABCbar' ~~ / foo [ A B C ] + bar /; +# The previous line returns `True`. +# We match the "abc" 1 or more time (the `+` was applied to the group). -# But this does not go far enough, because we can't actually get back what we matched. +# But this does not go far enough, because we can't actually get back what +# we matched. # Capture: We can actually *capture* the results of the regexp, using parentheses. so 'fooABCABCbar' ~~ / foo ( A B C ) + bar /; # `True`. (we keep `so` here and use `$/` below) @@ -1165,13 +1263,15 @@ say $/; # Will print some weird stuff (we'll explain) (or "Nil" if nothing match # As we also said before, it has array indexing: say $/[0]; #=> 「ABC」 「ABC」 - # These weird brackets are `Match` objects. So here, we have an array of that. -say $0; # the same as above. + # These weird brackets are `Match` objects. + # Here, we have an array of these. +say $0; # The same as above. # Our capture is `$0` because it's the first and only one capture in the regexp. # You might be wondering why it's an array, and the answer is simple: # Some capture (indexed using `$0`, `$/[0]` or a named one) will be an array -# IF it can have more than one element (so, with `*`, `+` and any `**`, but not with `?`). +# IFF it can have more than one element +# (so, with `*`, `+` and any `**`, but not with `?`). # Let's use examples to see that: so 'fooABCbar' ~~ / foo ( A B C )? bar /; # `True` say $/[0]; #=> 「ABC」 @@ -1206,7 +1306,8 @@ sub MAIN($name) { say "Hello, you !" } # t.pl # And since it's a regular Perl 6 sub, you can haz multi-dispatch: -# (using a "Bool" for the named argument so that we get `--replace` instead of `--replace=`) +# (using a "Bool" for the named argument so that we get `--replace` +# instead of `--replace=1`) subset File of Str where *.IO.d; # convert to IO object, then check the file exists multi MAIN('add', $key, $value, Bool :$replace) { ... } @@ -1218,8 +1319,9 @@ multi MAIN('import', File, Str :$as) { ... } # omitting parameter name # t.pl [--replace] add # t.pl remove # t.pl [--as=] import (File) -# As you can see, this is *very* powerful. It even went as far as to show inline the constants. -# (the type is only displayed if 1. there's no argument name 2. it's a named argument) +# As you can see, this is *very* powerful. +# It even went as far as to show inline the constants. +# (the type is only displayed if the argument is `$`/is named) ``` If you want to go further, you can: