Posts Tagged ‘perl6’

Day 4: Testing

December 4, 2009

Perl authors have a long tradition of shipping test cases with their modules, and in Perl 6 we plan to continue with that nice tradition.

And testing is very easy. The traditional perlish way is to print data in the Test Anything Protocol. But you don’t have to do that yourself, you can use a module for that.

Assume you have written a nice factorial function

 sub fac(Int $n) {
     [*] 1..$n
 }

Currently it doesn’t matter for us how that function works – we want to find out if it does. So let’s test it:

 use v6;

 sub fac(Int $n) {
     [*] 1..$n
 }

 use Test;
 plan 6;

 is fac(0), 1,  'fac(0) works';
 is fac(1), 1,  'fac(1) works';
 is fac(2), 2,  'fac(2) works';
 is fac(3), 6,  'fac(3) works';
 is fac(4), 24, 'fac(4) works';

 dies_ok { fac('oh noes i am a string') }, 'Can only call it with ints';

And let’s run it:

 $ perl6 fac-test.pl
 1..6
 ok 1 - fac(0) works
 ok 2 - fac(1) works
 ok 3 - fac(2) works
 ok 4 - fac(3) works
 ok 5 - fac(4) works
 ok 6 - Can only call it with ints

In detail: use Test; loads the testing module, plan 6; declares that we plan to run six tests. Then five lines of the pattern is $got, $expected, $description follow. is() does string comparison, but since integers always stringify the same way, that’s fine.

Finally with dies_ok { $some_code }, $description we test that calling the function with a non-integer argument is a fatal error.

The output contains the test plan 1..6, followed by one line for each test. That starts with ok (or not ok if the test failed), the test number, space, dash, space and test description.

If you run more tests, you don’t want to look through every test output carefully, but you want a summary. The prove command from Perl 5 gives you such a summary:

 prove --exec perl6 fac-test.pl
 fac-test.pl .. ok
 All tests successful.
 Files=1, Tests=6, 11 wallclock secs ( 0.02 usr  0.00 sys + 10.26 cusr  0.17 csys = 10.45 CPU)
 Result: PASS

You can also put all your test files in a directory, let’s call it t/, and run prove recursively on all .t files in that dir:

 prove --exec perl6 -r t

Putting that line in your Makefile is also nice, so that you can just type
make test to run the tests.

Day 3: static types and multi subs

December 3, 2009

The third box is ready for opening this Advent. Inside…well, looks like two gifts! Inside the box are static types and multi subs.

In Perl 5, $scalar variables could contain either references or values. Specifically, the values could be anything. They could be integers, strings, numbers, dates: you name it. This offers some flexibility, but at the cost of clarity.

Perl 6 is going to change that with its static types. If you want a particular variable, you place the type name in between my and $variable-type. As an example, to set up a variable to be an Int, one can do this:

my Int $days = 24;

Other static types are as follows:

  • my Str $phrase = "Hello World";
  • my Num $pi = 3.141e0;
  • my Rat $other_pi = 22/7;

If you still want the old behavior of the variables, you can either choose not to declare a static type or use Any instead.

This gift can easily go hand in hand with the second gift inside the box today: multi subs. What exactly are multi subs? In short, multi subs allow for the overloading of sub names. While multi subs can also do so much more, those are gifts for another day. For now, here are some subs that can be useful:


multi sub identify(Int $x) {
    return "$x is an integer.";
}

multi sub identify(Str $x) {
    return qq<"$x" is a string.>;
}

multi sub identify(Int $x, Str $y) {
    return "You have an integer $x, and a string \"$y\".";
}

multi sub identify(Str $x, Int $y) {
    return "You have a string \"$x\", and an integer $y.";
}

multi sub identify(Int $x, Int $y) {
    return "You have two integers $x and $y.";
}

multi sub identify(Str $x, Str $y) {
    return "You have two strings \"$x\" and \"$y\".";
}

say identify(42);
say identify("This rules!");
say identify(42, "This rules!");
say identify("This rules!", 42);
say identify("This rules!", "I agree!");
say identify(42, 24);

There is plenty to take advantage of with these two gifts. Try playing around with them, and keep coming back to our tree for more gifts that can use these features to their fullest extent. ☺

Day 2: The beauty of formatting

December 2, 2009

Unwrapping the second gift brought to you by Perl 6 this Advent, we find… a method named .fmt.

If you’re familiar with sprintf, you’ll feel right at home with .fmt. If you haven’t heard about sprintf before, or if you’ve heard of it but are a bit fuzzy on the details, you might want to skim the perldoc page. Don’t drown in it, though; it’s longish. Just savour it.

Back to .fmt, sprintf‘s spunky little sister. Here are a few ways to use .fmt to format strings and integers.

  say 42.fmt('%+d')                # '+42'
  say 42.fmt('%4d')                # '  42'
  say 42.fmt('%04d')               # '0042'
  say :16<1337f00d>.fmt('%X')      # '1337F00D'

All this is good and well, but not really more than a shorter method form of sprintf. Big deal, right?

What I haven’t told you yet is that .fmt is overloaded, and works differently on arrays (or more precisely, lists):

  say <huey dewey louie>.fmt       # 'huey dewey louie'
  say <10 11 12>.fmt('%x')         # 'a b c'
  say <1 2 3>.fmt('%02d', '; ')    # '01; 02; 03'

Similarly, it’s overridden on hashes (or rather, mappings):

  say { foo => 1, bar => 2 }.fmt   # 'foo     1
                                   #  bar     2'
  say { Apples => 5, Oranges => 10 }.fmt('%s cost %d euros')
                                   # 'Apples cost 5 euros
                                   #  Oranges cost 10 euros'
  say { huey => 1, dewey => 2, louie => 3 }.fmt('%s', ' -- ')
                                   # 'huey -- dewey -- louie'

The way hashing works may give your output a different order than the ones shown above. Oh, and there’s an overloaded .fmt for pairs as well, but it works analogously to the one for hashes.

.fmt is a useful little tool to have when you want to change some value, or an array or a hash of values, into to some given format. It’s like sprintf, but tailored to Do What You Mean for arrays and hashes, too.

There’s only one risk in all of this: Perl 6 might soil the reputation of the Perl family of languages by simply being too darn readable. In order to counter this risk, I leave a small parting gift in the form of a simple-but-dense Christmas tree printing Perl 6 one liner:

  $ perl6 -e 'say " "x 9-$_,"#"x$_*2-1 for 0..9,2 xx 3'

          #
         ###
        #####
       #######
      #########
     ###########
    #############
   ###############
  #################
         ###
         ###
         ###
[*] If you are using Windows, remember you need to switch the quotes around
c:\>perl6.exe -e "say ' 'x 9-$_,'#'x$_*2-1 for 0..9,2 xx 3"

Follow

Get every new post delivered to your Inbox.

Join 43 other followers