diff options
author | samcv <samantham@posteo.net> | 2016-10-27 01:38:21 -0700 |
---|---|---|
committer | ven <vendethiel@hotmail.fr> | 2016-10-27 10:38:21 +0200 |
commit | 46a02d6ee2cb29b9e0cea00a02a9f60e80e508cb (patch) | |
tree | a6b48343cc303bb902f3f7e81ddcf699b1e35ca0 | |
parent | 086284b2604303bdf609ef56014e66318406d804 (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.markdown | 169 |
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 : ) |