Archive for December, 2009

Day 15: .pick your game

December 15, 2009

Another college semester has ended, or is soon ending, for many of us in the United States. I feel it’s appropriate that this gift will involve some fun. The gift is the ability to .pick things.

.pick allows for picking random elements from a list. Perl 5 allowed doing so through this syntax:

my @dice = (1, 2, 3, 4, 5, 6);
my $index = int (rand() * scalar @dice);
print $dice[$index] . "\n"; 
> 5

Perl 6 allows simplifying this, while at the same time picking more than one element.

my @dice = 1..6;
say @dice.pick(2).join(" ");
> 3 4

With just a set of dice, it is already possible to have a role playing session with your friends. Now, let's see how much attack I can do with 10 d6s...

my @dice = 1..6;
say @dice.pick(10).join(" ");
> 5 3 1 4 2 6

For those wondering, the above result is not a typo. .pick's behavior is actually consistent with its name. When you pick something out, you generally keep it out. If you want to put the item back in, allowing the same item to be drawn again, use the :replace adverb in the second parameter.

my @dice = 1..6;
say @dice.pick(10, :replace).join(" ");
> 4 1 5 6 4 3 3 5 1 1

Note to game masters: don't invite me to your D&D games unless you need someone with terrible dice luck. ;)

There is no specific order the list items have to be in for .pick to work its magic. Take the values of monopoly money, for instance:

my @dice = <1 5 10 20 50 100 500>;
say @dice.pick(10, :replace).join(" ");
> 20 50 100 500 500 10 20 5 50 20

When dice aren't available, a deck of cards is usually on hand. This version is very basic, but is meant to get ideas going.

use v6;
class Card
{
  has $.rank;
  has $.suit;

  multi method Str()
  {
    return $.rank ~ $.suit;
  }
}

my @deck;
for <A 2 3 4 5 6 7 8 9 T J Q K> -> $rank
{
  for <♥ ♣ ♦ ♠> -> $suit
  {
    @deck.push(Card.new(:$rank, :$suit));
  }
}
# Shuffle the cards.
@deck .= pick(*);
say @deck.Str;
> Not outputting the results here.

What does the pick(*) do? Call that a sneak peak for another gift. For now, see if you can improve on the card code and make a deck class.

With that, I hope I have proven that Perl 6 is fun. It certainly gets a high mark from me. ✓

Day 14: Going to the Rats

December 14, 2009

As I hinted at back in the in the Day 1 post, Perl 6 has rational numbers. They are created in the most straightforward fashion, by dividing an integer with another integer. But it can be a bit hard to see that there is anything unusual about the result:

> say (3/7).WHAT
Rat()
> say 3/7
0.428571428571429

When you convert a Rat to a Str (for example, to "say" it), it converts to a decimal representation. This is based on the principle of least surprise: people generally expect 1/4 to equal 0.25. But the precision of the Rat is exact, rather than the approximation you'd get from a floating point number like a Num:

> say (3/7).Num + (2/7).Num + (2/7).Num - 1;
-1.11022302462516e-16
> say 3/7 + 2/7 + 2/7 - 1
0

The most straightforward way to see what is going on inside the Rat is to use the .perl method. .perl is a standard Perl 6 method which returns a human-readable string which, when eval'd, recreates the original object as closely as is possible:

> say (3/7).perl
3/7

You can also pick at the components of the Rat:

> say (3/7).numerator
3
> say (3/7).denominator
7
> say (3/7).nude.perl
[3, 7]

All the standard numeric operators and operations work on Rats. The basic arithmetic operators will generate a result which is also a Rat if that is possible; the rest will generate Nums:

> my $a = 1/60000 + 1/60000; say $a.WHAT; say $a; say $a.perl
Rat()
3.33333333333333e-05
1/30000
> my $a = 1/60000 + 1/60001; say $a.WHAT; say $a; say $a.perl
Num()
3.33330555601851e-05
3.33330555601851e-05
> my $a = cos(1/60000); say $a.WHAT; say $a; say $a.perl
Num()
0.999999999861111
0.999999999861111

(Note that the 1/60000 + 1/60000 didn't work in the last official release of Rakudo, but is fixed in the Rakudo github repository.)

There also is a nifty method on Num which creates a Rat within a given tolerance of the Num (default is 1e-6):

> say 3.14.Rat.perl
157/50
> say pi.Rat.perl
355/113
> say pi.Rat(1e-10).perl
312689/99532

One interesting development which has not made it into the main Rakudo build yet is decimal numbers in the source are now spec'd to be Rats. Luckily this is implemented in the ng branch, so it is possible to demo how it will work once it is in mainstream Rakudo:

> say 1.75.WHAT
Rat()
> say 1.75.perl
7/4
> say 1.752.perl
219/125

One last thing: in Rakudo, the Rat class is entirely implemented in Perl 6. The source code is thus a pretty good example of how to implement a numeric class in Perl 6.

Day 13: Junctions

December 13, 2009

Among the many exciting things in Perl 6, junctions are one of my favourites. While I know I don’t really comprehend everything you can do with them, there are a few useful tricks which I think most people will appreciate, and it is those which I’m going to cover as today’s gift.

Junctions are values which have (potentially) more than one value at once. That sounds odd, so let’s get thinking about some code which uses them. First, let’s take an example. Suppose you want to check a variable for a match against a set of numbers:

if $var == 3 || $var == 5 || $var == 7 { ... }

I've never liked that kind of testing, seeing as how it requires much repetition. With an any junction we can rewrite this test:

if $var == any(3, 5, 7) { ... }

How does this work? Right near the core of Perl 6 is a concept called junctive autothreading. What this means is that, most of the time, you can pass a junction to anything expecting a single value. The code will run for each member of the junction, and the result will be all those results combined in the same kind of junction which was originally passed.

In the sample above, the infix:<==> operator is run for each element of the junction to compare them with $var. The results of each test are combined into a new any junction, which is then evaluated in Boolean context by the if statement. An any junction in Boolean context is true if any of its values are true, so if $var matches any value in the junction, the test will pass.

This can save a lot of duplicated code, and looks quite elegant. There's another way to write it, as any junctions can also be constructed using the infix:<|> operator:

if $var == 3|5|7 { ... }

What if you want to invert this kind of test? There's another kind of junction that's very helpful, and it's called none:

if $var == none(3, 5, 7) { ... }

As you may have guessed, a none junction in Boolean context is true only if none of its elements are true.

Junctive autothreading also applies in other circumstances, such as:

my $j = any(1, 2, 3);
my $k = $j + 2;

What will this do? By analogy to the first example, you can probably guess that $k will end up being any(3, 4, 5).

There is an important point to note in these examples. We're talking about junctive autothreading, which should give you a hint. By the Perl 6 spec, the compiler is free to run these multiple operations on junctions in different threads so that they can execute in parallel. Much as with hyperoperators, you need to be aware that this could happen and avoid anything which would make a mess if run simultaneously.

The last thing I want to talk about is how junctions work with smartmatching. This is really just another instance of autothreading, but there are some other junction types which become particularly useful with smartmatching.

Say you have a text string, and you want to see if it matches all of a set of regexes:

$string ~~ /<first>/ & /<second>/ & /<third>/

Assuming, of course, you have defined regexes called first, second and third. Rather like |, & is an infix operator which creates junctions, this time all junctions which are only true if all their members are true.

The great thing about junctions is that they have this behaviour without the routine you're passing them to having to know about it, so you can pass junctions to almost any library or core function and expect this kind of behaviour (it is possible for a routine to deliberately notice junctions and treat them how it prefers rather than using the normal autothreading mechanism). So if you have a routine which takes a value to smartmatch something against, you can pass it a junction and get that flexibility in the smartmatch for free. We use this in the Perl 6 test suite, with functions like Test::Util::is_run, which runs some code in another interpreter and smartmatches against its output.

To finish off, here are some other useful things you can do with junctions. First, checking if $value is present in @list:

any(@list) == $value

Junction constructors can work quite happily with the elements of arrays, so this opens up many possibilities. Others include:

all(@list) > 0; # All members greater than zero?
all(@a) == any(@b); # All elements of @a present in @b?

Go experiment, and have fun!

Day 12: Modules and Exporting

December 12, 2009

Today I’d like to talk about a fairly fundamental subject: libraries.

To write a library in Perl 6, we use the “module” keyword:

module Fancy::Utilities {
    sub lolgreet($who) {
        say "O HAI " ~ uc $who;
    }
}

Put that in Fancy/Utilities.pm somewhere in $PERL6LIB and we can use it like the following:

use Fancy::Utilities;
Fancy::Utilities::lolgreet('Tene');

That's hardly ideal.  Just like in Perl 5, we can indicate that some symbols from the module should be made available in the lexical scope of the code loading the module.  We've got a rather different syntax for it, though:

# Utilities.pm
module Fancy::Utilities {
  sub lolgreet($who) is export {
    say "O HAI " ~ uc $who;
  }
}

# foo.pl
use Fancy::Utilities;
lolgreet('Jnthn');

If you don't specify further, symbols marked "is export" are exported by default.  We can also choose to label symbols as being exported as part of a different named group:

module Fancy::Utilities {
 sub lolgreet($who) is export(:lolcat, :greet) {
  say "O HAI " ~ uc $who;
 }
 sub nicegreet($who) is export(:greet, :DEFAULT) {
  say "Good morning, $who!"; # Always morning?
 }
 sub shortgreet is export(:greet) {
  say "Hi!";
 }
 sub lolrequest($item) is export(:lolcat) {
  say "I CAN HAZ A {uc $item}?";
 }
}

Those tags can be referenced in the code loading this module to choose which symbols to import:

use Fancy::Utilities; # Just get the DEFAULTs
use Fancy::Utilities :greet, :lolcat;
use Fancy::Utilities :ALL; # Everything marked is export

Multi subs are export by default, so you only need to label them if you want to change that.

multi sub greet(Str $who) { say "Good morning, $who!" }
multi sub greet() { say "Hi!" }
multi sub greet(Lolcat $who) { say "O HAI " ~ $who.name }

Classes are just a specialization of modules, so you can export things from them as well.  In addition, you can export a method to make it available as a multi sub.  For example, the setting exports the "close" method from the IO class so you can call "close($fh);"

class IO {
    ...
    method close() is export {
        ...
    }
    ...
}

Perl 6 does support importing symbols by name from a library, but Rakudo does not yet implement it.

Day 11: Classes, attributes, methods and more

December 11, 2009

We excitedly tear the shiny wrapping paper off today’s gift, and inside we find something that nobody could object to! It’s the Perl 6 object model, in all its class-declaring, role-composing, meta-modelling glory. But before we get too carried away with the high-powered stuff, let’s see just how easy it is to write a class in Perl 6.

class Dog {
    has $.name;
    method bark($times) {
        say "w00f! " x $times;
    }
}

We start off by using the class keyword. If you're coming from a Perl 5 background, you can think of class as being a bit like a variant of package that gives you a bunch of classy semantics out of the box.

Next, we use the has keyword to declare an attribute along with an accessor method. The . that you see in the name is a twigil. Twigils tell you something special about the scoping of a variable. The . twigil means "attribute + accessor". Other options are:

has $!name;       # Private; only visible in the class
has $.name is rw; # Generates an l-value accessor

Next comes a method, introduced using the method keyword. method is like sub, but adds an entry to the methods table of the class. It also automatically takes the invocant for you, so you don't have to write it in the parameter list. It is available through self.

All classes inherit a default constructor, named new, which maps named parameters to attributes. We can call this on Dog - the type object of the Dog class - to get a new instance.

my $fido = Dog.new(name => 'Fido');
say $fido.name;  # Fido
$fido.bark(3);   # w00f! w00f! w00f!

Notice that the method call operator in Perl 6 is . rather than Perl 5's ->. It's 50% shorter, and will be familiar to developers coming from a range of other languages.

Of course, there's inheritance, so we can introduce a yappy puppy.

class Puppy is Dog {
    method bark($times) {
        say "yap! " x $times;
    }
}

There's also support for delegation.

class DogWalker {
    has $.name;
    has Dog $.dog handles (dog_name => 'name');
}
my $bob = DogWalker.new(name => 'Bob', dog => $fido);
say $bob.name;      # Bob
say $bob.dog_name;  # Fido

Here, we declare that we'd like calls to the method dog_name on the class DogWalker to forward to the name method of the contained Dog. Renaming is just one option that is available; the delegation syntax offers many other alternatives.

The beauty is more than skin deep, however. Beneath all of the neat syntax is a meta-model. Classes, attributes and methods are all first class in Perl 6, and are represented by meta-objects. We can use these to introspect objects at runtime.

for Dog.^methods(:local) -> $meth {
    say "Dog has a method " ~ $meth.name;
}

The .^ operator is a variant on the . operator, but instead makes a call on the metaclass - the object that represents the class. Here, we ask it to give us a list of the methods defined within that class (we use :local to exclude those inherited from parent classes). This doesn't just give us a list of names, but instead a list of Method objects. We could actually invoke the method using this object, but in this case we've just ask for its name.

Those of you into meta-programming and looking forward to extending the Perl 6 object model will be happy to know that there's also a declarational aspect to all of this, so uses of the method keyword actually compile down to calls to add_method on the meta-class. Perl 6 not only offers you a powerful object model out of the box, but also provides opportunities for it to grow to meet other future needs that we didn't think of yet.

These are just a handful of the great things that the Perl 6 object model has to offer; maybe we'll discover more of them in some of the other gifts under the tree. :-)

Day 10: A Regex Story

December 10, 2009

On this tenth day of advent, we have the gift of a story …

Once upon a time in a land closer than you might think, an apprentice Perl 6 programmer named Tim was working on a simple parsing problem. His boss (let’s just call him Mr. C) had asked him to parse log files containing inventory information to make sure that there were only valid lines within the file. Each valid line within the file looked like this:

    <part number> <quantity> <color> <description>

So the Perl 6 apprentice, having some familiarity with regular expressions wrote a nice little regex that could be used to identify valid lines. The code that validated each line looked like this:

    next unless $line ~~ / ^^ \d+ \s+ \d+ \s+ \S+ \s+ \N* $$ /

The ~~ operator causes the regex on the right hand side to be matched against the scalar on the left hand side. In the regex itself, ^^ matches the beginning of a line, \d+ matches one or more digits (as the part number and quantity were so composed), \S+ matches one or more non- whitespace characters, \N* matches zero or more non-newline characters, \s+ matches whitespace in between each of these and $$ matches the end of a line. This being Perl 6, these individual components of the regex could be spread out a bit with spaces in between so that it could be more readable. All was good.

But then Mr. C decided that it would be nicer if the individual pieces of information could also be extracted from each in addition to validating it. Tim thought, "No problem, I'll just use capturing parentheses". And that's just what he did:

    next unless $line ~~ / ^^ (\d+) \s+ (\d+) \s+ (\S+) \s+ (\N*) $$ /

After a successful pattern match, each parenthesized portion is available either as part of the match object itself ($/) via $/[0], $/[1], $/[2], or $/[3]. Or it could be accessed via the special variables $0, $1, $2, or $3. Tim was happy. Mr. C was happy.

But then it was discovered that some of the lines didn't separate the color from the description and that these lines should be considered valid too. Lines where the color was integrated into the description were written a special way. They were always of the form:

    <part number> <quantity> <description> (<color>)

Where description, as before, could be any number of characters including spaces. "Blah!" thought Tim, "now this simple parser suddenly seems more complicated." Luckily, Tim knew of a place to ask for help. He quickly logged on to irc.freenode.org, joined the #perl6 channel, and asked for help. Someone suggested that he should name the individual parts of his regex to make things easier and then use an alternation to match one or the other alternatives for the last part of the regex.

First, Tim tried naming the parts of his regex. Looking at the synopsis for Perl 6 regex, Tim found he could assign into the match object, so that's what he did:

    next unless $line ~~ / ^^ $<product>=(\d+) \s+ $<quantity>=(\d+) \s+ $<color>=(\S+) \s+ $<description>=(\N*) $$ /

Now, after a successful match, the individual pieces are available via the match object or via special variables $<product>, $<quantity>, $<color>, and $<description>. This was turning out easier than expected and Tim was feeling quite confident. Next he added the alternation to distinguish between the two different valid lines:

    next unless $line ~~ / ^^
        $<product>=(\d+) \s+ $<quantity>=(\d+) \s+
        [
        | $<description>=(\N*) \s+ '(' $<color>=(\S+) ')'
        | $<color>=(\S+) \s+ $<description>=(\N*)
        ]
      $$
    /

In order to isolate the alternation from the rest of the regex, Tim surrounded it with grouping brackets ([ and ]). These group a portion of a regex much like parentheses only without capturing into $0 and friends. Since he needed to match literal parentheses, Tim took advantage of another useful Perl 6 regex feature: quoted strings are matched literally. And because of the assignments within the regex, $<color> and $<description> always contain the appropriate part of the string.

Tim was elated! He showed his code to Mr. C and Mr. C was elated too! "Well done Tim!" said Mr. C.

Everybody was happy. Tim beamed with pride.

However, after the initial glow of success faded, Tim started looking at his work with a more critical eye. For some of the lines where the color was at the end of the description, it was described as "( color)" or "( color )" or "( color )". His current regex worked, but it would include the color as part of the description and wouldn't set $<color> at all. That hardly seemed appropriate. Tim initially fixed this by adding more \s*:

    next unless $line ~~ / ^^
        $<product>=(\d+) \s+ $<quantity>=(\d+) \s+
        [
        | $<description>=(\N*) \s+ '(' \s* $<color>=(\S+) \s* ')'
        | $<color>=(\S+) \s+ $<description>=(\N*)
        ]
      $$
    /

This worked well, but the regex was starting to look a little cluttered. Again, Tim turned to #perl6 for help.

This time someone named PerlJam piped up, "Why don't you put your regex in a grammar? That's what you're effectively doing by assigning each piece to a variable within the match object." Wha??? Tim had no idea what PerlJam was talking about. After a brief exchange, Tim thought he understood and knew where to look if he needed more information. After thanking PerlJam, he went back to coding. This time the regex virtually disappeared as it turned into a grammar. Here's what that grammar and matching code looked like:

grammar Inventory {
    regex product { \d+ }
    regex quantity { \d+ }
    regex color { \S+ }
    regex description { \N* }
    regex TOP { ^^ <product> \s+ <quantity>  \s+
                [
                | <description> \s+ '(' \s* <color> \s*  ')'
                | <color> \s+ <description>
                ]
                $$
    }
}

# ... and then later where the match happens
next unless Inventory.parse($line);

"Well," thought Tim, "it is certainly more organized."

Each of his variables in the previous incarnation of the regex simply became named regex within the grammar. Within Perl 6 regex, named regex are matched by simply enclosing the name within angle brackets (< and >). The specially named regex TOP is used when Grammar.parse is called with the scalar to match against. And the behavior is exactly the same as before because when a named regex matches as part of another regex, the text that was matched is saved in the match object and referenced by that name.

And though there was still room for improvement, both Tim and Mr. C were very happy with the result.

The End

* At the time of posting, Rakudo cannot correctly use this grammar to parse lines in the format

    <part number> <quantity> <description> (<color>)

Day 9: Having beautiful arguments (and parameters)

December 9, 2009

On the ninth day of advent, we unwrap… the syntax for parameters and arguments.

You may or may not be familiar with the way Perl 5 does parameter handling in subroutines. It goes something like this:

  sub sum {
    [+] @_
  }
  say sum 100, 20, 3;  # 123

The [+] is Perl 6, but we might as well have written that as my $i = 0; $i += $_ for @_; $i, and the above would have worked in Perl 5. The important point is that, in Perl 6 as well as in Perl 5, when you call a subroutine, your parameters can be found in @_. You unpack them, and you do your thing.

This system is extremely flexible, because it doesn't impose any mechanism on the handling of parameters; it's all up to you, the programmer. It's also tedious, and favours boilerplate to some extent. Take this fictional example:

  sub grade_essay {
    my ($essay, $grade) = @_;
    die 'The first argument must be of type Essay'
      unless $essay ~~ Essay;
    die 'The second argument must be an integer between 0 and 5'
      unless $grade ~~ Int && $grade ~~ 0..5;

    %grades{$essay} = $grade;
  }

(You'd have to use isa instead of ~~ and $grades instead of %grades to make this work in Perl 5, but apart from that, this code would work in Perl 5 as well as in Perl 6.)

Now, for a moment, look at the above, and despair about the amount of manual unpacking and verification you have to make. Feel it? Good.

Perl 5 solves this by giving you excellent CPAN modules, such as Sub::Signatures and MooseX::Declare, for example. Just include them, and you're set.

Perl 6 solves it by giving you a few more defaults. By "a few more", I really mean "make sure you don't drool on your keyboard". In Perl 6, I would have written the above routine like this:

  sub grade_essay(Essay $essay, Int $grade where 0..5) {
    %grades{$essay} = $grade;
  }

Now we're talking. It has the same runtime semantics as the longer version above. And I didn't have to import any CPAN modules, either.

Sometimes it's convenient to provide default values to parameters:

  sub entreat($message = 'Pretty please, with sugar on top!', $times = 1) {
    say $message for ^$times;
  }

The default values need not be constants, and they can in fact use earlier parameters:

  sub xml_tag ($tag, $endtag = matching_tag($tag) ) {...}

If your default is unspecified, just mark the parameter as optional without giving it a default, by using ?:

  sub deactivate(PowerPlant $plant, Str $comment?) {
    $plant.initiate_shutdown_sequence();
    say $comment if $comment;
  }

One feature I particularly like is that you can refer to the parameters by name when calling, passing the named arguments in any order you like. I can never remember the parameter order in functions like this:

  sub draw_line($x1, $y1, $x2, $y2) { ... }

  draw_line($x1, $y1, $x2, $y2);  # phew. got it right this time.
  draw_line($x1, $x2, $y1, $y2);  # dang! :-/

There's a way to refer to the parameters by name, which makes this problem melt away:

  draw_line(:x1($x1), :y1($y1), :x2($x2), :y2($y2));  # works
  draw_line(:x1($x1), :x2($x2), :y1($y1), :y2($y2));  # also works!

The colon means "here comes a named argument", and the whole construct is to be read as :name_of_parameter($variable_passed_in). There's a short form that can be used when the parameter and the variable happen to have the same name, though:

  draw_line(:$x1, :$y1, :$x2, :$y2);  # works
  draw_line(:$x1, :$x2, :$y1, :$y2);  # also works!

I like the short form. I find it causes my code to be more readable.

If you, as the API author, want to force people to use named arguments — which might actually be appropriate in the case of draw_line — you need only supply the colons in the subroutine signature.

  sub draw_line(:$x1,  :$y1,  :$x2,  :$y2 ) { ... }  # optional nameds

But be careful, named arguments are optional by default! In other words, the above is equivalent to this:

  sub draw_line(:$x1?, :$y1?, :$x2?, :$y2?) { ... }  # optional nameds

If you want to explicitly make parameters required, you can append a ! to them:

  sub draw_line(:$x1!, :$y1!, :$x2!, :$y2!) { ... }  # required nameds

Now the caller has to pass them, just as with ordinary positional parameters.

What about varargs? Say you want an arbitrary number of arguments passed in. No problem: just make the parameter an array and precede it with a *:

  sub sum(*@terms) {
    [+] @terms
  }
  say sum 100, 20, 3;  # 123

I use the same example as we started out with to make a point: when you don't supply a signature to your subroutine, what you end up with is the signature *@_. This is the signature that emulates Perl 5 behaviour.

But an array with a * in front of it (a 'slurpy array') only captures positional arguments. If you want to capture named arguments, you'd use a 'slurpy hash':

  sub detect_nonfoos(:$foo!, *%nonfoos) {
    say "Besides 'foo', you passed in ", %nonfoos.keys.fmt("'%s'", ', ');
  }

  detect_nonfoos(:foo(1), :bar(2), :baz(3));
       # Besides 'foo', you passed in 'bar', 'baz'

Oh, and this might be a good time to mention that you can also pass in named parameters with a more hash-like syntax, like so:

  detect_nonfoos(foo => 1, bar => 2, baz => 3);
       # Besides 'foo', you passed in 'bar', 'baz'

Here's one important difference to Perl 5: parameters are readonly by default:

  sub increase_by_one($n) {
    ++$n
  }

  my $value = 5;
  increase_by_one($value);  # boom

There are two chief reasons for making parameters readonly; one being efficiency. Optimizers like when variables are read-only. The other reason has to do with encouraging the right habits in the programmer, and make it slightly more cumbersome to be sloppy. Functional programming is good not only for the optimizer, but for the soul as well.

Here's what you need to do to make the above work:

  sub increase_by_one($n is rw) {
    ++$n
  }

  my $value = 5;
  say increase_by_one($value);  # 6

Sometimes is rw is what you want, but sometimes you'd rather be modifying a copy of whatever was sent in. That's when you use is copy:

  sub format_name($first, $middle is copy, $last) {
    $middle .= substr(0, 1);
    "$first $middle. $last"
  }

The original will be left unchanged.

In Perl 6, when you pass in an array or a hash, it doesn't flatten out over several arguments by default. Instead, you have to use the | to make it flatten.

  sub list_names($x, $y, $z) {
    "$x, $y and $z"
  }

  my @ducklings = <huey dewey louie>;
  try {
    list_names(@ducklings);
  }
  say $!;                       # 'Not enough positional parameters passed;
                                #  got 1 but expected 3'
  say list_names(|@ducklings);  # 'huey, dewey and louie'

Similarly, if you flatten a hash, its contents will be sent in as named arguments to the routine.

Just as you can pass in arrays and hashes, you can also pass in code blocks:

  sub traverse_inorder(TreeNode $n, &action) {
    traverse_inorder($n.left, &action) if $n.left;
    action($n);
    traverse_inorder($n.right, &action) if $n.right;
  }

The three sigils are really type constraints:

  @  Array    (actually, Positional)
  %  Hash     (actually, Associative)
  &  Code     (actually, Callable)

...with the $ sigil working as the unconstrained version.

Watch out! An easy trap that people fall into is specifying the type constraint twice, both through a type and through a sigil:

  sub f(Array @a) { ... }  # WRONG, unless you mean Array of Array
  sub f(      @a) { ... }  # probably what you meant
  sub f(Int   @a) { ... }  # Array of Int

If you followed through to this point, you deserve another Perl 6 one-liner.

  $ perl6 -e '.fmt("%b").trans("01" => " #").say for <734043054508967647390469416144647854399310>.comb(/.**7/)'
  ###           ##   ###
  # #  ##  # ##  #  #
  ### #  # ##    #  ####
  #   #### #     #  #   #
  #   #    #     #  #   #
  #    ##  #     ##  ###

Day 8: .comb your constraints

December 8, 2009

We have hit the point where the previous gifts are useful for the current gifts. Today is a dual set: the comb method and the idea of constraints.

Similar to the static types previous defined, constraints allow fine control in writing subroutines and methods. In many other programming languages, you have to pass parameters into a subroutine and then validate the input that comes in. With constraints, you can do the validation right in the declaration.

Take this basic example. If the integer is even, I don't want to deal with this subroutine. In Perl 5, it would be written something similar to this:

sub very_odd
{
    my $odd = shift;
    unless ($odd % 2)
    {
        return undef;
    }
    # Process the odd number here.
}

In Perl 6, this can be simplified thusly:

sub very_odd(Int $odd where {$odd % 2})
{
    # Process the odd number here
}

If you attempt to call very_odd with an even number, you will get an error. Do not fret though: you can use the multi sub functionality to give even numbers a chance to shine...maybe. ;)

multi sub very_odd(Int $odd where {$odd % 2})
{
    # Process the odd number here
}
multi sub very_odd(Int $odd) { return Bool::False; }

These constraints can be useful when paired with the .comb method. What exactly is .comb? For those that brush their own hair, you generally use a comb to get the strands you want and settle them somewhere on your head. For those that like using .split, it's the opposite: instead of separating a Str by what you don't want, you separate it by what you do. This simple piece of code should demonstrate that:

say "Perl 6 Advent".comb(/<alpha>/).join('|');
say "Perl 6 Advent".comb(/<alpha>+/).join('|');

Regex patterns will most likely be covered another day, but a quick preview won't hurt. The first line will print P|e|r|l|A|d|v|e|n|t: it gets every alphabetic character and puts it into a temporary array. It is then joined together with the pipe character. The second line is similar, only it grabs as many alphabetic characters as it can, resulting in Perl|Advent.

The power of .comb is much more, however. Once you have combed out what you wanted, you can manipulate the strands. If you have a basic string of ASCII hex characters, you can use the hyperoperators to change each piece into the ASCII equivalent!

say "5065726C36".comb(/<xdigit>**2/)».fmt("0x%s")».chr
# Outputs "Perl6"

For those intimidated by that, you can find also use the .map method.

say "5065726C36".comb(/<xdigit>**2/).map: { chr '0x' ~ $_ } ;
# Outputs "Perl6"

Remember, this is Perl. There is more than one way to do it. ☺

With all of the gifts that have been presented today, I now have a challenge for all of you. With the assistance of Kyle Hasselbacher, I was able to make a decent version of the ancient Caesar Cipher using constraints, .comb, and the old style .map.

use v6;

sub rotate_one( Str $c where { $c.chars == 1 }, Int $n ) {
    return $c if $c !~~ /<alpha>/;
    my $out = $c.ord + $n;
    $out -= 26 if $out > ($c eq $c.uc ?? 'Z'.ord !! 'z'.ord);
    return $out.chr;
}

sub rotate(Str $s where {$s.chars}, Int $n = 3)
{
    return ($s.comb.map: { rotate_one( $_, $n % 26 ) }).join( '' );
}

die "Usage:\n$*PROGRAM_NAME string number_for_rotations" unless @*ARGS == 2;

my Str $mess = @*ARGS[0];
my Int $rotate = @*ARGS[1].Int;

say qq|"$mess" rotated $rotate characters gives "{rotate($mess,$rotate)}".|;

I would like to see how the rest of you can code this algorithm using Perl 6 and the gifts so far. After all, the language can only get better with more usage.

Day 7: Looping for fun and profit

December 7, 2009

Any programmer who’s ever used a language which has them probably knows that loops are incredibly useful. In languages which provide them, foreach loops for iterating over arrays or lists tend to end up being very common. In Perl 5, these loops were provided by the foreach keyword, although you could also write for, sharing a keyword with the more general C-style for loops.

In Perl 6, that's all changed.

for is now exclusively for iterating over lists. foreach has disappeared, and C-style for loops are handled by the new keyword loop. We're not going to discuss those today, but we are going to focus on the new for loop, which combines with some other Perl 6 language features to deliver an enormously flexible and powerful construct.

Let's look at a basic case.

for 1, 2, 3, 4 { .say }

There some immediately noticeable things about the syntax here. There are no brackets around the list construction, which is something that extends throughout Perl 6. Generally, you need a lot fewer brackety characters than in Perl 5. Much like in Perl 5, the loop variable is $_ by default. The method call of say with no invocant is the same as saying $_.say. Note that in Perl 6, you cannot say say with no argument to default to $_, you have to use the .say form, or specify $_ explicitly.

The block doesn't have to be an ordinary block. It can be a pointy block, which lets you name your loop variable using the pointy block's parameter capability.

for 1, 2, 3, 4 -> $i { $i.say }

A pointy block is a bit like an anonymous subroutine, except it doesn't catch return exceptions. If you call return inside a pointy block, the enclosing routine will return.

Pointy blocks can take more than one parameter in their parameter lists. What happens if you do that?

for 1, 2, 3, 4 -> $i, $j { "$i, $j".say }

Well, if you run it, you get:

1 2
3 4

So what's actually happened is that you've iterated over the list two elements at a time. This works for any number of parameters, with the minimum of one, degenerating to using $_ if you provide no explicit parameters yourself.

Having realised we can do this, what can we do with the generation of the list we iterate over? Well of course, we can use an array variable:

for @array { .say }

Although in many simple cases, we might prefer to use map:

@array.map: *.say;

Or a hyperoperator, if order and sequentiality isn't important:

@array».say;

But neither of those things are today's subject.

We might generate a list of numbers using the range constructor &infix:<..>:

for 1..4 { .say }

It's very common that we want to generate a list of $n numbers beginning with 0, such as array indicies. We could write 0..$n-1, or using a variant of the range constructor 0..^$n, but Perl 6 provides a handy shortcut in the form of prefix:<^>:

for ^4 { .say }

Which will output:

0
1
2
3

One reason people often fall back on C-style for loops in Perl 5 is because they need to know what index in the array they are at for each item, or because they need to iterate over two or more arrays in parallel. Perl 6 offers a shortcut here, with the infix:<Z> zip operator.

for @array1 Z @array2 -> $one, $two { ... }

Assuming the two arrays are the same length, $one will be each element of @array1 and $two will be the corresponding element of @array2. If they are different lengths, iteration will stop when the end of the shorter array is reached.

With this knowledge, and the awareness that Perl 6 has lazy list generators, we can easily include the array index in the iteration:

for ^Inf Z @array -> $index, $item { ... }

Although if infinite lists make you nervous,

for ^@array.elems Z @array -> $index, $item { ... }

will give you the same results, but the most elegant presentation is probably:

for @array.kv -> $index, $item { ... }

@array.kv returns the keys and values interleaved, where the keys of an array are the element indices, so iterating over them two at a time has the desired effect.

Hopefully this post has given you an idea of the flexibility inherent in Perl 6's for loops and how easy they can be to use for a variety of common tasks. Before we part, I'm going to answer one final question I know somebody's been thinking.

What, you ask, if I want to iterate over four arrays at once?

for @one Z @two Z @three Z @four -> $one, $two, $three, $four { ... }

That's a list associative infix operator, that is. Enjoy.

Day 6: Going Into Hyperspace

December 6, 2009

pmichaud introduced Perl 6′s hyper operators yesterday. I’d like to explore these powerful meta operators further.

First, for simplicity I’m going to code a helper function, lsay, to easily get nice-looking output of lists. The sub is created using our so you can use it on the REPL.

our sub lsay(@a) { @a.perl.say }

Then we can start looking at hyperoperator examples. For this post I'm going to use >> and << instead of » and «, mostly because they are easier on my eyes. (I'm afraid I may need to get glasses.) » and « are generally considered the true form of the operator, but the longer ASCII version will work as well.

First, the most basic: adding two lists of the same length:

> lsay (1, 2, 3, 4) <<+>> (3, 1, 3, 1)
[4, 3, 6, 5]
> lsay (1, 2, 3, 4) >>+<< (3, 1, 3, 1)
[4, 3, 6, 5]

If the lengths of the arrays are the same, there's no difference between the two forms. But if the length is different:

> lsay (1, 2, 3, 4) <<+>> (3, 1)
[4, 3, 4, 5]
> lsay (1, 2, 3, 4) >>+<< (3, 1)
Sorry, right side is too short and not dwimmy.

The rule is that whatever is pointed to by the pointy end of the hyperoperator can be extended if it is shorter than the other end; it is extended by repeating the last element of that list. Whatever is at the blunt end of the hyperoperator cannot be extended. All combinations are allowed, so you can specify that only the left side can be extended (<<+<<), only the right side (>>+>>), both sides can be extended (<<+>>), or neither side can be extended (>>+<<). Single scalars extend as well:

> lsay (1, 2, 3, 4) >>+>> 2
[3, 4, 5, 6]
> lsay 3 <<+<< (1, 2, 3, 4)
[4, 5, 6, 7]

So that's the basics of using hyperoperator with an infix operator. You can also use them with prefix and postfix operators:

> lsay ~<<(1, 2, 3, 4)
["1", "2", "3", "4"]
> my @a= (1, 2, 3, 4); @a>>++; lsay @a;
[2, 3, 4, 5]

You can also:

> lsay (0, pi/4, pi/2, pi, 2*pi)>>.sin
[0, 0.707106781186547, 1, 1.22464679914735e-16, -2.44929359829471e-16]
> lsay (-1, 0, 3, 42)>>.Str
["-1", "0", "3", "42"]

That is to say >>. works to call a method on every member of the list.

However much you are tempted to write @array>>.say, don't do it. It may work in the current version of Rakudo, but by using the hyper operator you are promising the operation is parallelizable, and the order of the operations on the list(s) is not fixed. The hope is that future versions of Perl 6 will automatically run these operations in parallel.

Other quick notes: The hyperoperators don't just work with the built-in set of operators. They will work with any new operator you define as well. (That works now in Rakudo, mostly.) They will work with the in-place operators, e.g. @a >>/=>> 2 to divide an entire array by 2. (This does not work in current Rakudo.) They will work with multi-dimensional lists, with trees, and with hashes; see S03 Hyper operators. (As far as I know, these do not yet work in Rakudo either.)

I don't know too many examples yet of source code using hyperoperators extensively, though LastOfTheCarelessMen's Vector class is a good if straightforward start -- it implements an N-dimensional vector class without a single explicit loop.


Follow

Get every new post delivered to your Inbox.

Join 37 other followers