summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorsamcv <samantham@posteo.net>2016-10-27 01:38:21 -0700
committerven <vendethiel@hotmail.fr>2016-10-27 10:38:21 +0200
commit46a02d6ee2cb29b9e0cea00a02a9f60e80e508cb (patch)
treea6b48343cc303bb902f3f7e81ddcf699b1e35ca0
parent086284b2604303bdf609ef56014e66318406d804 (diff)
[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
-rw-r--r--perl6.html.markdown169
1 files changed, 120 insertions, 49 deletions
diff --git a/perl6.html.markdown b/perl6.html.markdown
index d31955f0..8fcf9a02 100644
--- a/perl6.html.markdown
+++ b/perl6.html.markdown
@@ -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 : )