summaryrefslogtreecommitdiffhomepage
path: root/perl6.html.markdown
diff options
context:
space:
mode:
Diffstat (limited to 'perl6.html.markdown')
-rw-r--r--perl6.html.markdown179
1 files changed, 92 insertions, 87 deletions
diff --git a/perl6.html.markdown b/perl6.html.markdown
index b2d7d48c..323bc0b3 100644
--- a/perl6.html.markdown
+++ b/perl6.html.markdown
@@ -1,17 +1,16 @@
---
-name: perl6
category: language
language: perl6
filename: learnperl6.pl
contributors:
- - ["Nami-Doc", "http://github.com/Nami-Doc"]
+ - ["vendethiel", "http://github.com/vendethiel"]
---
-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 at
+least the next hundred years.
-Perl 6 runs on [the Parrot VM](http://parrot.org/), the JVM
-and [the MoarVM](http://moarvm.com).
+The primary Perl 6 compiler is called [Rakudo](http://rakudo.org), which runs on
+the JVM and [the MoarVM](http://moarvm.com).
Meta-note : the triple pound signs are here to denote headlines,
double paragraphs, and single notes.
@@ -73,7 +72,7 @@ say @array; #=> a 6 b
# except they get "flattened" (hash context), removing duplicated keys.
my %hash = 1 => 2,
3 => 4;
-my %hash = autoquoted => "key", # keys get auto-quoted
+my %hash = foo => "bar", # keys get auto-quoted
"some other" => "value", # trailing commas are okay
;
my %hash = <key1 value1 key2 value2>; # you can also create a hash
@@ -94,7 +93,6 @@ say %hash<key2>; # 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 `&`.
sub say-hello { say "Hello, world" }
sub say-hello-to(Str $name) { # You can provide the type of an argument
@@ -105,8 +103,8 @@ sub say-hello-to(Str $name) { # You can provide the type of an argument
## 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)` (Perl's 'null'-like value) if I don't have
+ an argument passed, or I'll return my argument";
$arg;
}
with-optional; # returns Any
@@ -123,14 +121,14 @@ hello-to('You'); #=> Hello, You !
## You can also, by using a syntax akin to the one of hashes (yay unified syntax !),
## pass *named* arguments to a `sub`.
-# They're optional, and will default to "Any" (Perl's "null"-like value).
+# They're optional, and will default to "Any".
sub with-named($normal-arg, :$named) {
say $normal-arg + $named;
}
with-named(1, named => 6); #=> 7
# There's one gotcha to be aware of, here:
# If you quote your key, Perl 6 won't be able to see it at compile time,
-# and you'll have a single Pair object as a positional paramater,
+# and you'll have a single Pair object as a positional parameter,
# which means this fails:
with-named(1, 'named' => 6);
@@ -141,7 +139,7 @@ sub with-mandatory-named(:$str!) {
say "$str !";
}
with-mandatory-named(str => "My String"); #=> My String !
-with-mandatory-named; # run time error: "Required named parameter not passed"
+with-mandatory-named; # run time error: "Required named parameter not passed"
with-mandatory-named(3); # run time error: "Too many positional parameters passed"
## If a sub takes a named boolean argument ...
@@ -160,7 +158,7 @@ named-def; #=> 5
named-def(def => 15); #=> 15
# Since you can omit parenthesis to call a function with no arguments,
-# you need "&" in the name to capture `say-hello`.
+# you need "&" in the name to store `say-hello` in a variable.
my &s = &say-hello;
my &other-s = sub { say "Anonymous function !" }
@@ -171,8 +169,8 @@ sub as-many($head, *@rest) { # `*@` (slurpy) will basically "take everything els
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 (the *) did not
+ # consume the parameter before.
## You can call a function with an array using the
# "argument list flattening" operator `|`
@@ -195,7 +193,7 @@ sub mutate($n is rw) {
say "\$n is now $n !";
}
-# If what you want is a copy instead, use `is copy`.
+# If what you want a copy instead, use `is copy`.
# A sub itself returns a container, which means it can be marked as rw:
my $x = 42;
@@ -211,7 +209,7 @@ say $x; #=> 52
# - `if`
# 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`),
+# Only these values are Falsey: 0, (), {}, "", Nil, A type (like `Str` or `Int`),
# and of course False itself.
# Every other value is Truthy.
if True {
@@ -232,7 +230,7 @@ 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 much more
+# - `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,
@@ -288,7 +286,7 @@ for @array -> $variable {
# That means you can use `when` in a `for` just like you were in a `given`.
for @array {
say "I've got $_";
-
+
.say; # This is also allowed.
# A dot call with no "topic" (receiver) is sent to `$_` by default
$_.say; # the above and this are equivalent.
@@ -375,10 +373,14 @@ say @array[^10]; # you can pass arrays as subscripts and it'll return
say join(' ', @array[15..*]); #=> 15 16 17 18 19
# which is equivalent to:
say join(' ', @array[-> $n { 15..$n }]);
+# Note: if you try to do either of those with an infinite array,
+# you'll trigger an infinite loop (your program won't finish)
+
+# You can use that in most places you'd expect, even assigning to an array
+my @numbers = ^20;
-# You can use that in most places you'd expect, even assigning to an array
-my @numbers = ^20;
-my @seq = 3, 9 ... * > 95; # 3 9 15 21 27 [...] 81 87 93 99
+# Here numbers increase by "6"; more on `...` operator later.
+my @seq = 3, 9 ... * > 95; # 3 9 15 21 27 [...] 81 87 93 99;
@numbers[5..*] = 3, 9 ... *; # even though the sequence is infinite,
# only the 15 needed values will be calculated.
say @numbers; #=> 0 1 2 3 4 3 9 15 21 [...] 81 87
@@ -523,7 +525,7 @@ map(sub ($a, $b) { $a + $b + 3 }, @array); # (here with `sub`)
# The constructs for declaring types are "class", "role",
# which you'll see later.
-# For now, let us examinate "subset":
+# For now, let us examine "subset":
# a "subset" is a "sub-type" with additional checks.
# For example: "a very big integer is an Int that's greater than 500"
# You can specify the type you're subtyping (by default, Any),
@@ -606,40 +608,39 @@ sub foo {
bar(); # call `bar` in-place
}
sub bar {
- say $*foo; # `$*a` will be looked in the call stack, and find `foo`'s,
+ say $*foo; # `$*foo` will be looked in the call stack, and find `foo`'s,
# 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`. 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)
+# methods with `method`. Every attribute that is private is named `$!attr`.
+# Immutable public attributes are named `$.attr`
+# (you can make them mutable with `is rw`)
-# (Perl 6's object model ("SixModel") is very flexible,
+# 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.
# From inside the class, use `$!field` to modify it.
- has $.other-field is rw; # You can obviously mark a public field `rw`.
+ has $.other-field is rw; # You can mark a public attribute `rw`.
has Int $!private-field = 10;
method get-value {
$.field + $!private-field;
}
-
+
method set-value($n) {
# $.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` is `rw`.
}
-
+
method !private-method {
say "This method is private to the class !";
}
@@ -654,23 +655,22 @@ $a.other-field = 10; # This, however, works, because the public field
# is mutable (`rw`).
## Perl 6 also has inheritance (along with multiple inheritance)
-# (though considered a misfeature by many)
class A {
has $.val;
-
+
submethod not-inherited {
say "This method won't be available on B.";
say "This is most useful for BUILD, which we'll see later";
}
-
+
method bar { $.val * 5 }
}
class B is A { # inheritance uses `is`
method foo {
say $.val;
}
-
+
method bar { $.val * 10 } # this shadows A's `bar`
}
@@ -697,20 +697,20 @@ role PrintableVal {
# you "import" a mixin (a "role") with "does":
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 !):
method access {
say $!counter++;
}
-
+
# However, this:
# method print {}
# 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.
}
@@ -736,7 +736,7 @@ try {
# You can throw an exception using `die`:
die X::AdHoc.new(payload => 'Error !');
-# You can access the last exception with `$!` (usually used in a `CATCH` block)
+# You can access the last exception with `$!` (use `$_` in a `CATCH` block)
# There are also some subtelties to exceptions. Some Perl 6 subs return a `Failure`,
# which is a kind of "unthrown exception". They're not thrown until you tried to look
@@ -749,7 +749,7 @@ fail "foo"; # We're not trying to access the value, so no problem.
try {
fail "foo";
CATCH {
- default { say "It threw because we try to get the fail's value!" }
+ default { say "It threw because we tried to get the fail's value!" }
}
}
@@ -761,25 +761,21 @@ try {
### 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. (Packages are the lowest common denomitor)
+# and `enum`) are actually packages. (Packages are the lowest common denominator)
# Packages are important - 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`:
+# You're not supposed to use the package keyword, usually:
+# you use `class Package::Name::Here;` to declare a class,
+# 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
+unit module Parse::Text; # file-scoped form
grammar Parse::Text::Grammar { # A grammar is a package, which you could `use`
}
-# NOTE for Perl 5 users: even though the `package` keyword exists,
-# the braceless form is invalid (to catch a "perl5ism"). This will error out:
-# package Foo; # because Perl 6 will think the entire file is Perl 5
-# Just use `module` or the brace version of `package`.
-
# You can use a module (bring its declarations into scope) with `use`
use JSON::Tiny; # if you installed Rakudo* or Panda, you'll have this module
say from-json('[1]').perl; #=> [1]
@@ -795,10 +791,8 @@ my $actions = JSON::Tiny::Actions.new;
# You've already seen `my` and `has`, we'll now explore the others.
## * `our` (happens at `INIT` time -- see "Phasers" below)
-# Along with `my`, there are several others declarators you can use.
-# The first one you'll want for the previous part is `our`.
+# It's like `my`, but it also creates a package variable.
# (All packagish things (`class`, `role`, etc) are `our` by default)
-# it's like `my`, but it also creates a package variable:
module Foo::Bar {
our $n = 1; # note: you can't put a type constraint on an `our` variable
our sub inc {
@@ -810,7 +804,7 @@ module Foo::Bar {
say "Can't access me from outside, I'm my !";
}
}
-
+
say ++$n; # lexically-scoped variables are still available
}
say $Foo::Bar::n; #=> 1
@@ -827,7 +821,7 @@ constant why-not = 5, 15 ... *;
say why-not[^5]; #=> 5 15 25 35 45
## * `state` (happens at run time, but only once)
-# State variables are only executed one time
+# State variables are only initialized one time
# (they exist in other langages such as C as `static`)
sub fixed-rand {
state $val = rand;
@@ -860,7 +854,7 @@ for ^5 -> $a {
## * Compile-time phasers
BEGIN { say "[*] Runs at compile time, as soon as possible, only once" }
-CHECK { say "[*] Runs at compile time, instead as late as possible, only once" }
+CHECK { say "[*] Runs at compile time, as late as possible, only once" }
## * Run-time phasers
INIT { say "[*] Runs at run time, as soon as possible, only once" }
@@ -868,10 +862,21 @@ END { say "Runs at run time, as late as possible, only once" }
## * Block phasers
ENTER { say "[*] Runs everytime you enter a block, repeats on loop blocks" }
-LEAVE { say "Runs everytime you leave a block, even when an exception happened. Repeats on loop blocks." }
+LEAVE { say "Runs everytime you leave a block, even when an exception
+ happened. Repeats on loop blocks." }
+
+PRE { say "Asserts a precondition at every block entry,
+ before ENTER (especially useful for loops)" }
+# exemple:
+for 0..2 {
+ PRE { $_ > 1 } # This is going to blow up with "Precondition failed"
+}
-PRE { say "Asserts a precondition at every block entry, before ENTER (especially useful for loops)" }
-POST { say "Asserts a postcondition at every block exit, after LEAVE (especially useful for loops)" }
+POST { say "Asserts a postcondition at every block exit,
+ after LEAVE (especially useful for loops)" }
+for 0..2 {
+ POST { $_ < 2 } # This is going to blow up with "Postcondition failed"
+}
## * Block/exceptions phasers
sub {
@@ -889,12 +894,12 @@ for ^5 {
## * Role/class phasers
COMPOSE { "When a role is composed into a class. /!\ NOT YET IMPLEMENTED" }
-# They allow for cute trick or clever code ...:
-say "This code took " ~ (time - CHECK time) ~ "s to run";
+# They allow for cute tricks or clever code ...:
+say "This code took " ~ (time - CHECK time) ~ "s to compile";
# ... or clever organization:
sub do-db-stuff {
- ENTER $db.start-transaction; # New transaction everytime we enter the sub
+ $db.start-transaction; # start a new transaction
KEEP $db.commit; # commit the transaction if all went well
UNDO $db.rollback; # or rollback if all hell broke loose
}
@@ -1018,7 +1023,7 @@ sub circumfix:<[ ]>(Int $n) {
$n ** $n
}
say [5]; #=> 3125
- # circumfix is around. Again, not whitespace.
+ # circumfix is around. Again, no whitespace.
sub postcircumfix:<{ }>(Str $s, Int $idx) {
# post-circumfix is
@@ -1042,7 +1047,7 @@ postcircumfix:<{ }>(%h, $key, :delete); # (you can call operators like that)
# *everything* -- with great power comes great responsibility)
## Meta operators !
-# Oh boy, get ready. Get ready, because we're dwelving deep
+# Oh boy, get ready. Get ready, because we're delving 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).
@@ -1050,9 +1055,9 @@ postcircumfix:<{ }>(%h, $key, :delete); # (you can call operators like that)
# Basically, they're operators that apply another operator.
## * Reduce meta-operator
-# It's a prefix meta-operator that takes a binary functions and
+# It's a prefix meta-operator that takes a binary function and
# one or many lists. If it doesn't get passed any argument,
-# it either return a "default value" for this operator
+# it either returns a "default value" for this operator
# (a meaningless value) or `Any` if there's none (examples below).
#
# Otherwise, it pops an element from the list(s) one at a time, and applies
@@ -1073,8 +1078,8 @@ say [//] Nil, Any, False, 1, 5; #=> False
# Default value examples:
-say [*] (); #=> 1
-say [+] (); #=> 0
+say [*] (); #=> 1
+say [+] (); #=> 0
# meaningless values, since N*1=N and N+0=N.
say [//]; #=> (Any)
# There's no "default value" for `//`.
@@ -1087,7 +1092,7 @@ say [[&add]] 1, 2, 3; #=> 6
# This one is an infix meta-operator than also can be used as a "normal" operator.
# It takes an optional binary function (by default, it just creates a pair),
# and will pop one value off of each array and call its binary function on these
-# until it runs out of elements. It runs the an array with all these new elements.
+# until it runs out of elements. It returns an array with all of these new elements.
(1, 2) Z (3, 4); # ((1, 3), (2, 4)), since by default, the function makes an array
1..3 Z+ 4..6; # (5, 7, 9), using the custom infix:<+> function
@@ -1107,8 +1112,7 @@ say [[&add]] 1, 2, 3; #=> 6
# (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, 3, 6 ... 10; # this dies 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
@@ -1220,7 +1224,7 @@ so 'abbbbbbc' ~~ / a b ** 3..* c /; # `True` (infinite ranges are okay)
# they use a more perl6-ish syntax:
say 'fooa' ~~ / f <[ o a ]>+ /; #=> 'fooa'
# You can use ranges:
-say 'aeiou' ~~ / a <[ e..w ]> /; #=> 'aeiou'
+say 'aeiou' ~~ / a <[ e..w ]> /; #=> 'ae'
# Just like in normal regexes, if you want to use a special character, escape it
# (the last one is escaping a space)
say 'he-he !' ~~ / 'he-' <[ a..z \! \ ]> + /; #=> 'he-he !'
@@ -1240,14 +1244,14 @@ so 'foo!' ~~ / <-[ a..z ] + [ f o ]> + /; # True (the + doesn't replace the left
# 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 /;
+so 'foo012012bar' ~~ / foo [ '01' <[0..9]> ] + bar /;
# The previous line returns `True`.
-# We match the "abc" 1 or more time (the `+` was applied to the group).
+# We match the "012" 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.
# Capture: We can actually *capture* the results of the regexp, using parentheses.
-so 'fooABCABCbar' ~~ / foo ( A B C ) + bar /; # `True`. (using `so` here, `$/` below)
+so 'fooABCABCbar' ~~ / foo ( 'A' <[A..Z]> 'C' ) + bar /; # `True`. (using `so` here, `$/` below)
# So, starting with the grouping explanations.
# As we said before, our `Match` object is available as `$/`:
@@ -1285,10 +1289,12 @@ say $/[0][0].Str; #=> ~
# This stems from a very simple fact: `$/` does not contain strings, integers or arrays,
# it only contains match objects. These contain the `.list`, `.hash` and `.Str` methods.
-# (but you can also just use `match<key>` for hash access and `match[idx]` for array access)
+# (but you can also just use `match<key>` for hash access
+# and `match[idx]` for array access)
say $/[0].list.perl; #=> (Match.new(...),).list
- # We can see it's a list of Match objects. Those contain a bunch of infos:
- # where the match started/ended, the "ast" (see actions later), etc.
+ # We can see it's a list of Match objects. Those contain
+ # a bunch of infos: where the match started/ended,
+ # the "ast" (see actions later), etc.
# You'll see named capture below with grammars.
## Alternatives - the `or` of regexps
@@ -1326,14 +1332,14 @@ so 'ayc' ~~ / a [ b | y ] c /; # `True`. Obviously enough ...
### Extra: the MAIN subroutime
# The `MAIN` subroutine is called when you run a Perl 6 file directly.
-# It's very powerful, because Perl 6 actually parses the argument
+# It's very powerful, because Perl 6 actually parses the arguments
# and pass them as such to the sub. It also handles named argument (`--foo`)
# and will even go as far as to autogenerate a `--help`
sub MAIN($name) { say "Hello, $name !" }
# This produces:
# $ perl6 cli.pl
# Usage:
-# t.pl <name>
+# t.pl <name>
# And since it's a regular Perl 6 sub, you can haz multi-dispatch:
# (using a "Bool" for the named argument so that we can do `--replace`
@@ -1344,9 +1350,9 @@ multi MAIN('add', $key, $value, Bool :$replace) { ... }
multi MAIN('remove', $key) { ... }
multi MAIN('import', File, Str :$as) { ... } # omitting parameter name
# This produces:
-# $ perl 6 cli.pl
+# $ perl6 cli.pl
# Usage:
-# t.pl [--replace] add <key> <value>
+# t.pl [--replace] add <key> <value>
# t.pl remove <key>
# t.pl [--as=<Str>] import (File)
# As you can see, this is *very* powerful.
@@ -1398,7 +1404,7 @@ for <well met young hero we shall meet later> {
# (explained in details below).
.say
}
-
+
if rand == 0 ff rand == 1 { # compare variables other than `$_`
say "This ... probably will never run ...";
}
@@ -1427,7 +1433,7 @@ for <well met young hero we shall meet later> {
# A flip-flop can change state as many times as needed:
for <test start print it stop not printing start print again stop not anymore> {
.say if $_ eq 'start' ^ff^ $_ eq 'stop'; # exclude both "start" and "stop",
- #=> "print this printing again"
+ #=> "print it print again"
}
# you might also use a Whatever Star,
@@ -1459,4 +1465,3 @@ If you want to go further, you can:
- Come along on `#perl6` at `irc.freenode.net`. The folks here are always helpful.
- Check the [source of Perl 6's functions and classes](https://github.com/rakudo/rakudo/tree/nom/src/core). Rakudo is mainly written in Perl 6 (with a lot of NQP, "Not Quite Perl", a Perl 6 subset easier to implement and optimize).
- Read [the language design documents](http://design.perl6.org). They explain P6 from an implementor point-of-view, but it's still very interesting.
-