[perl6] Explain orelse operator, add more information about exceptions, add an Iterables section... (#2505)

* More clear names for the module and variables demonstrating declarators (our) for sub's and a few more details in comments

* $! is only set when we use "try" not when we disarm an exception with or/orelse thanks to ZoffixZnet for the information here provided here: https://rt.perl.org/Ticket/Display.html?id=129923

* Fix the example from the last commit. Some changes in the try/catch paragraph

* Change it so the vim modeline doesn't show up in the final html file(not even as a comment)

* Minor grammar fix

* Add more information about the .exception method and explain how orelse differs from the or operator

* Add link to the Perl6 docs and explain that while the Perl 6 advent calander is a great reference it may be a little older (Posts stopped in Dec of 2015).  Also make the columns fit better to 80 characters

* Fix in issue with a few of the regex examples, where Perl 6 would warn because the spacing was ambiguous. Explain how you must use two spaces between strings so spacing isn't ambiguous or use the :s adverb to make whitespace meaningful explicitly.  Also explain 'm' and using delimiters other than / /

* Improve the readability of the phasers introduction

* Fix the remaining regex that will warn because of ambiguous spacing

* Add an example for ‘quietly’ since it has been implemented now

* Update link for precedence order to point to current documentation

* Add a section on iterables and show examples for using the lazy method

* Some corrections

* Change downloaded filename to .p6 instead of .pl

* Show vertical line for 80 column width in vim modeline

* Update the exceptions section to vendethiel's suggestions
This commit is contained in:
samcv 2016-10-27 01:38:21 -07:00 committed by ven
parent 086284b260
commit 46a02d6ee2

View File

@ -1,7 +1,7 @@
---
category: language
language: perl6
filename: learnperl6.pl
filename: learnperl6.p6
contributors:
- ["vendethiel", "http://github.com/vendethiel"]
---
@ -798,19 +798,47 @@ class Item does PrintableVal {
### Exceptions
# Exceptions are built on top of classes, in the package `X` (like `X::IO`).
# You can access the last exception with the special variable `$!`
# (use `$_` in a `CATCH` block) Note: This has no relation to $!variables.
# In Perl6 exceptions are automatically 'thrown'
open 'foo'; #> Failed to open file foo: no such file or directory
# It will also print out what line the error was thrown at and other error info
# You can throw an exception using `die`:
open 'foo' or die 'Error!'; #=> Error!
die 'Error!'; #=> Error!
# Or more explicitly:
die X::AdHoc.new(payload => 'Error!');
# In Perl 6, `orelse` is similar to the `or` operator, except it only matches
# undefined variables instead of anything evaluating as false.
# Undefined values include: `Nil`, `Mu` and `Failure` as well as `Int`, `Str`
# and other types that have not been initialized to any value yet.
# You can check if something is defined or not using the defined method:
my $uninitialized;
say $uninitiazilzed.defined; #> False
# When using `orelse` it will disarm the exception and alias $_ to that failure
# This will avoid it being automatically handled and printing lots of scary
# error messages to the screen.
# We can use the exception method on $_ to access the exception
open 'foo' orelse say "Something happened {.exception}";
# This also works:
open 'foo' orelse say "Something happened $_"; #> Something happened
#> Failed to open file foo: no such file or directory
# Both of those above work but in case we get an object from the left side that
# is not a failure we will probably get a warning. We see below how we can use
# `try` and `CATCH` to be more specific with the exceptions we catch.
## Using `try` and `CATCH`
# By using `try` and `CATCH` you can contain and handle exceptions without
# disrupting the rest of the program.
# disrupting the rest of the program. `try` will set the last exception to
# the special variable `$!` Note: This has no relation to $!variables.
try open 'foo';
say "Well, I tried! $!" if defined $!; #> Well, I tried! Failed to open file
#foo: no such file or directory
# Now, what if we want more control over handling the exception?
# 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
# the block to `try`. Similar to how $_ was set when we 'disarmed' the
# exception with orelse, we also use $_ in the CATCH block.
# Note: ($! is only set *after* the `try` block)
# By default, a `try` has a `CATCH` block that catches
# any exception (`CATCH { default {} }`).
try { my $a = (0 %% 0); CATCH { say "Something happened: $_" } }
@ -877,7 +905,7 @@ module Hello::World { # Bracketed form
unit module Parse::Text; # file-scoped form
grammar Parse::Text::Grammar { # A grammar is a package, which you could `use`
}
} # You will learn more about grammars in the regex section
# 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:
@ -889,25 +917,33 @@ my $actions = JSON::Tiny::Actions.new;
# 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)
## * `our` declarations happen at `INIT` time -- (see "Phasers" below)
# It's like `my`, but it also creates a package variable.
# (All packagish things (`class`, `role`, etc) are `our` by default)
module Foo::Bar {
our $n = 1; # note: you can't put a type constraint on an `our` variable
our sub inc {
module Var::Increment {
our $our-var = 1; # Note: you can't put a type constraint like Int on an
my $my-var = 22; # `our` variable.
our sub Inc {
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.";
say "Don't do that. Seriously. You'll get burned.";
}
my sub unavailable { # `my sub` is the default
say "Can't access me from outside, I'm my !";
say "Can't access me from outside, I'm 'my'!";
}
say ++$n; # increment the package variable and output its value
say ++$our-var; # Increment the package variable and output its value
}
}
say $Foo::Bar::n; #=> 1
Foo::Bar::inc; #=> 2
Foo::Bar::inc; #=> 3
say $Var::Increment::our-var; #=> 1 This works
say $Var::Increment::my-var; #=> (Any) This will not work.
Var::Increment::Inc; #=> 2
Var::Increment::Inc; #=> 3 # Notice how the value of $our-var was
# retained.
Var::Increment::unavailable; #> Could not find symbol '&unavailable'
## * `constant` (happens at `BEGIN` time)
# You can use the `constant` keyword to declare a compile-time variable/symbol:
@ -944,10 +980,11 @@ for ^5 -> $a {
### 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 !)
# program. They are called phasers because they mark a change in the phase
# of a program. For example, when the program is compiled, a for loop runs,
# you leave a block, or 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).
# (those that can have a "[*]" in the beginning of their explanation text).
# Let's have a look !
## * Compile-time phasers
@ -1046,15 +1083,25 @@ constant thrice = gather for ^3 { say take $_ }; # Doesn't print anything
# versus:
constant thrice = eager gather for ^3 { say take $_ }; #=> 0 1 2
# - `lazy` - Defer actual evaluation until value is fetched (forces lazy context)
# Not yet implemented !!
### Iterables
# Iterables are objects that can be iterated similar to the `for` construct
# `flat`, flattens iterables:
say (1, 10, (20, 10) ); #> (1 10 (20 10)) Notice how grouping is maintained
say (1, 10, (20, 10) ).flat; #> (1 10 20 10) Now the iterable is flat
# - `lazy` - Defer actual evaluation until value is fetched (forces lazy context)
my @lazy-array = (1..100).lazy;
say @lazy-array.is-lazy; #> True # Check for lazyness with the `is-lazy` method.
say @lazy-array; #> [...] List has not been iterated on!
my @lazy-array { .print }; # This works and will only do as much work as is
# needed.
[//]: # ( TODO explain that gather/take and map are all lazy)
# - `sink` - An `eager` that discards the results (forces sink context)
constant nilthingie = sink for ^3 { .say } #=> 0 1 2
say nilthingie.perl; #=> Nil
# - `quietly` - Supresses warnings
# Not yet implemented !
# - `quietly` blocks will suppress warnings:
quietly { warn 'This is a warning!' }; #=> No output
# - `contend` - Attempts side effects under STM
# Not yet implemented !
@ -1064,7 +1111,7 @@ 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
# https://docs.perl6.org/language/operators#Operator_Precedence
# But first, we need a little explanation about associativity:
# * Binary operators:
@ -1258,7 +1305,7 @@ say @fib[^10]; #=> 1 1 2 3 5 8 13 21 34 55
# (grammars are actually classes)
# - Earliest declaration wins
say so 'a' ~~ /a/; #=> True
say so 'a' ~~ / a /; # More readable with some spaces!
say so 'a' ~~ / a /; #=> True # 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
@ -1274,50 +1321,63 @@ say so 'a' ~~ / a /; # More readable with some spaces!
# 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`. Wouldn't mean the same if `|` wasn't escaped
say so 'a|b' ~~ / a \| b /; # `True`. Another way to escape it.
# The whitespace in a regexp is actually not significant,
# unless you use the `:s` (`:sigspace`, significant space) modifier.
say so 'a b c' ~~ / a b c /; # `False`. Space is not significant here
say so 'a b c' ~~ /:s a b c /; # `True`. We added the modifier `:s` here.
# unless you use the `:s` (`:sigspace`, significant space) adverb.
say so 'a b c' ~~ / a b c /; #> `False`. Space is not significant here
say so 'a b c' ~~ /:s a b c /; #> `True`. We added the modifier `:s` here.
# If we use only one space between strings in a regex, Perl 6 will warn us:
say so 'a b c' ~~ / a b c /; #> 'False' #> Space is not significant here; please
# use quotes or :s (:sigspace) modifier (or, to suppress this warning, omit the
# space, or otherwise change the spacing)
# To fix this and make the spaces less ambiguous, either use at least two
# spaces between strings or use the `:s` adverb.
# As we saw before, we can embed the `:s` inside the slash delimiters, but we can
# also put it outside of them if we specify `m` for 'match':
say so 'a b c' ~~ m:s/a b c/; #> `True`
# By using `m` to specify 'match' we can also use delimiters other than slashes:
say so 'abc' ~~ m{a b c}; #> `True`
# Use the :i adverb to specify case insensitivity:
say so 'ABC' ~~ m:i{a b c}; #> `True`
# It is, however, important as for how modifiers (that you're gonna see just below)
# are applied ...
## Quantifying - `?`, `+`, `*` and `**`.
# - `?` - 0 or 1
so 'ac' ~~ / a b c /; # `False`
so 'ac' ~~ / a b? c /; # `True`, the "b" matched 0 times.
so 'abc' ~~ / a b? c /; # `True`, the "b" matched 1 time.
so 'ac' ~~ / a b c /; # `False`
so 'ac' ~~ / a b? c /; # `True`, the "b" matched 0 times.
so 'abc' ~~ / a b? c /; # `True`, the "b" matched 1 time.
# ... As you read just before, whitespace is important because it determines
# which part of the regexp is the target of the modifier:
so 'def' ~~ / a b c? /; # `False`. Only the `c` is optional
so 'def' ~~ / ab?c /; # `False`. Whitespace is not significant
so 'def' ~~ / a b c? /; # `False`. Only the `c` is optional
so 'def' ~~ / a b? c /; # `False`. Whitespace is not significant
so 'def' ~~ / 'abc'? /; # `True`. The whole "abc" group is optional.
# Here (and below) the quantifier applies only to the `b`
# - `+` - 1 or more
so 'ac' ~~ / a b+ c /; # `False`; `+` wants at least one matching
so 'abc' ~~ / a b+ c /; # `True`; one is enough
so 'abbbbc' ~~ / a b+ c /; # `True`, matched 4 "b"s
so 'ac' ~~ / a b+ c /; # `False`; `+` wants at least one matching
so 'abc' ~~ / a b+ c /; # `True`; one is enough
so 'abbbbc' ~~ / a b+ c /; # `True`, matched 4 "b"s
# - `*` - 0 or more
so 'ac' ~~ / a b* c /; # `True`, they're all optional.
so 'abc' ~~ / a b* c /; # `True`
so 'abbbbc' ~~ / a b* c /; # `True`
so 'aec' ~~ / a b* c /; # `False`. "b"(s) are optional, not replaceable.
so 'ac' ~~ / a b* c /; # `True`, they're all optional.
so 'abc' ~~ / a b* c /; # `True`
so 'abbbbc' ~~ / a b* c /; # `True`
so 'aec' ~~ / a b* c /; # `False`. "b"(s) are optional, not replaceable.
# - `**` - (Unbound) Quantifier
# 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`
so 'abbbbbbc' ~~ / a b ** 1..3 c /; # `False` (too much)
so 'abbbbbbc' ~~ / a b ** 3..* c /; # `True` (infinite ranges are okay)
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`
so 'abbbbbbc' ~~ / a b**1..3 c /; # `False` (too much)
so 'abbbbbbc' ~~ / a b**3..* c /; # `True` (infinite ranges are okay)
# - `<[]>` - Character classes
# Character classes are the equivalent of PCRE's `[]` classes, but
@ -1561,7 +1621,18 @@ for <a b c> {
If you want to go further, you can:
- Read the [Perl 6 Advent Calendar](http://perl6advent.wordpress.com/). This is probably the greatest source of Perl 6 information, snippets and such.
- Read the [Perl 6 Docs](https://docs.perl6.org/). This is a great
resource on Perl6. If you are looking for something, use the search bar.
This will give you a dropdown menu of all the pages referencing your search
term (Much better than using Google to find Perl 6 documents!)
- Read the [Perl 6 Advent Calendar](http://perl6advent.wordpress.com/). This
is a great source of Perl 6 snippets and explainations. If the docs don't
describe something well enough, you may find more detailed information here.
This information may be a bit older but there are many great examples and
explainations. Posts stopped at the end of 2015 when the language was declared
stable and Perl 6.c was released.
- 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.
[//]: # ( vim: set filetype=perl softtabstop=2 shiftwidth=2 expandtab cc=80 : )