From 1d931a37f2d428bc2d783f1a8597455db70a23de Mon Sep 17 00:00:00 2001 From: Nami-Doc Date: Tue, 22 Jul 2014 22:55:27 +0200 Subject: Declarators mention the six model clearer description of package/module etc clearer description of `$.` vs `$!` --- perl6.html.markdown | 97 +++++++++++++++++++++++++++++++++++++++++++---------- 1 file 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 -- cgit v1.2.3