summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--perl6.html.markdown97
1 files changed, 80 insertions, 17 deletions
diff --git a/perl6.html.markdown b/perl6.html.markdown
index 70799b29..5ead6560 100644
--- a/perl6.html.markdown
+++ b/perl6.html.markdown
@@ -360,29 +360,27 @@ sub bar {
### Object Model
## Perl 6 has a quite comprehensive object model
-## You declare a class with the keyword `class`, fields with `has`, methods with `method`
-## `$.` declares a public field, `$!` declares a private field
-## (a public field also has `$!`, which is its private interface)
+## 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.
# (Perl 6's object model ("P6Model") 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;
+ 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 Int $!private-field = 10;
-
+
method get-value {
$.field + $!private-field + $n;
}
method set-value($n) {
- # $.field = $n; # This fails, because a public field is actually an immutable container
- # (even from inside the class)
- # You either need to use `is rw` on the `has`
- # (which will make it mutable, even from outside the class)
- # or you need to use the `$!` version :
-
- $!field = $n; # This works, because `$!` is always mutable
+ # $.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).
}
method !private-method {
@@ -394,7 +392,8 @@ class A {
# 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 lacking the `is rw`
+#$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`).
## Perl 6 also has inheritance (along with multiple inheritance ... Considered a misfeature by many)
@@ -473,25 +472,89 @@ die X::AdHoc.new(payload => 'Error !');
# TODO CONTROL
### Packages
-# Packages play a big part in a language, and 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.
+# (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,
# the Comprehensive Perl Archive Network.
-# You can declare a mdule using the `module` keyword, and they can be nested:
+# 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
}
module Parse::Text; # file-scoped form
+grammar Parse::Text::Grammar { # A grammar is a fine 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]
-# Any class, role, is also a module
+# As said before, any part of the six model is also a package.
+# Since `JSON::Tiny` uses (its own) `JSON::Tiny::Actions` class, you can use it:
my $actions = JSON::Tiny::Actions.new;
# We'll see how to export variables and subs in the next part:
### Declarators
-TODO: my, our, state, constant.
+# In Perl 6, you get different behaviors based on how you declare a variable.
+# 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`.
+# (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 {
+ our sub available { # if you try to make scoped `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
+ say "Can't access me from outside, I'm my !";
+ }
+ }
+
+ say ++$n; # lexically-scoped variables are still available
+}
+say $Foo::Bar::n; #=> 1
+Foo::Bar::inc; #=> 2
+Foo::Bar::inc; #=> 3
+
+## * `constant` (happens at `BEGIN` time)
+# You can use the `constant` keyword to declare a compile-time variable/symbol:
+constant Pi = 3.14;
+constant $var = 1;
+
+## * `state` (happens at run time, but only once)
+# State variables are only executed one time
+# (they exist in other langages such as C as `static`)
+sub fixed-rand {
+ state $val = rand;
+ say $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:
+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`
+ }
+}
+
### Phasers