Author Archive

Day 14 – nextsame and its cousins

December 14, 2010

Maybe you’re familiar with the way the keyword super in Java allows you to delegate to the method (or constructor) of a base class. Perl 6 has something similar… but in a world with multiple inheritance and mixins it makes less sense to call it super. So it’s called nextsame. Here’s an example of its use:

class A {
    method sing {
        say "life is but a dream.";
    }
}

class B is A {
    method sing {
        say ("merrily," xx 4).join(" ");
        nextsame;
    }
}

class C is B {
    method sing {
        say "row, row, row your boat,";
        say "gently down the stream.";
        nextsame;
    }
}

Now, when we call C.new.sing, our class hierarchy will output this:

row, row, row your boat,
gently down the stream.
merrily, merrily, merrily, merrily,
life is but a dream.

You’ll note how the call finds its way from C.sing via B.sing over to A.sing. Those transitions are (of course) mediated by the nextsame calls. You’ll note the similarity to, for example, Java’s super.

But calling along the inheritance chain is not the only place where nextsame proves useful. Here’s an example not involving object orientation:

sub bray {
    say "EE-I-EE-I-OO.";
}

# Oh right, forgot to add the first line of the song...
&bray.wrap( {
    say "Old MacDonald had a farm,";
    nextsame;
} );

bray(); # Old MacDonald had a farm,
        # EE-I-EE-I-OO.

So that’s another reason nextsame is not called super: it’s not necessarily related to the base class, because there might not be a base class. Instead, there’s some more general phenomenon involved. What might that be?

Every time we do a call to something, there’s a part of the language runtime making sure that the call ends up in the right routine. Such a part is called a dispatcher. A dispatcher makes sure that the following multi call ends up in the appropriate routine:

multi foo(    $x) { say "Any argument" }
multi foo(Int $x) { say "Int argument" }

foo(42) # Int argument

(And a nextsame in the second multi foo would re-dispatch to the first. But that doesn’t work in Rakudo yet.)

Dispatchers are everywhere in Perl 6. They’re involved in method calls, so that a method can defer along the inheritance chain, as we did in the beginning of the post. They’re in wrapped routines, so that the code doing the wrapping can call into the code being wrapped. And they participate in multi dispatch, so that multi variants can defer to each other. It’s all the same principle, but in different guises.

And nextsame is just a way to talk directly to your friendly neighborhood dispatcher. By the way, the keyword is called nextsame because it instructs the dispatcher to defer to the next candidate with the same signature. There are variants, as you’ll see below.

You can use nextsame in mixins, too:

class A {
    method foo { "OH HAI" }
}

role LogFoo {
    method foo {
        note ".foo was called";
        nextsame;
    }
}

my $logged_A = A.new but LogFoo;

say $logged_A.foo; # .foo was called
                   # OH HAI

I like this way to use mixins to inject behavior. I once wrote a post about it, and jnthn has written a Perl 6 module that exploits it.

Though pretty cool, this use of nextsame isn’t really anything new; in fact it’s just another example of the defer-along-the-OO-callchain dispatcher. That’s because mixing in the role LogFoo with but causes an anonymous subclass to be created, one that also does LogFoo. So role mixin nextsame boils down to just inheritance nextsame. (But we don’t need to actually grok that to use it, and it still feels slightly magical and very nice to use.)

In summary, nextsame works in a lot of places you’d expect it to work, and it works the way you expect it to. It defers to the next thing.

Oh, and nextsame has three closely related cousin keywords:

nextsame             Defer with the same arguments, don't return
callsame             Defer with the same arguments, then  return

nextwith($p1, $p2, ...) Defer with these arguments, don't return
callwith($p1, $p2, ...) Defer with these arguments, then  return

Naturally, the other three can be used in the same situations nextsame can.

Day 7 – Lexical variables

December 7, 2010

Programming is tough going. Well, stringing together lines of code isn’t that difficult, and prototyping an idea can be pleasant and easy. But as the size of the program scales up, and the maintenance time lengthens, things tend to get tricky. Eventually, if we’re unlucky, we’re overcome by the complexity — not necessarily the complexity of the problem we started out solving, but the complexity of the program itself. We get gray hairs from debugging, or we’re simply at a loss for how to extend the program to do what we want.

So we turn to the history of programming, seeking advice as to how to combat complexity. And the answer sits there, clear as day: limit extent. If you’re architecting programs with hundreds or thousands of types of components, you’ll want those components to interact through only a very small set of surfaces… otherwise, you’ll simply lose control. Otherwise, combinatorics will defeat you.

We see this principle at every single level of programming, simply because it’s such a primary thing: Separation of Concerns, Do One Thing And Do It Well, BCNF, monads, routines, classes, roles, modules, packages. All of them urge us or guide us to limit the extent of things, so we don’t lose to combinatorics. Perhaps the simplest example of this is the lexical variable.

{
    my $var;
    # $var is visible in here
}
# $var is not visible out here

Yeah — that is today’s “cool feature”. :-) Here’s what makes it interesting:

Perl got this one wrong from version 1 and onwards. The default variable scope in Perl 5 is the “package variable”, a kind of global variable. Define something inside a block; still see it outside.

$ perl -v
This is perl 5, version 12, subversion 1 (v5.12.1)

$ perl -E '{ $var = 42 }; say $var'
42

$ perl -wE '{ my $var= 42 }; say $var'
Name "main::var" used only once: possible typo at -e line 1.
Use of uninitialized value $var in say at -e line 1.

In Perl 6, the lexical variable is the default. You won’t get past compilation if you try to pull off the above trick in Rakudo:

$ perl6 -e '{ $var = 42 }; say $var'    # gotta initialize with 'my'
===SORRY!===
Symbol '$var' not predeclared in <anonymous>

$ perl6 -e '{ my $var = 42 }; say $var' # still won't work! not visible outside
===SORRY!===
Symbol '$var' not predeclared in <anonymous>

You might say “okay, this is great for catching a typo now and then”. Yes, sure, but the big advantage is that this keeps you honest about variable scoping. And that helps you manage complexity.

Now let me just rush to the defense of Perl 5 by saying a variety of things at the same time. Perl 5 does try to steer you in the right way by having you use strict and use warnings by reflex; Perl 5 is bound by its promise of backwards compatibility, which is very good and noble; Perl 1 certainly was not about writing large applications and managing the resulting complexity; and global variables do make a lot of sense in a one-line script.

Perl 6 has an inherent focus to help you start small, and then help you put in more strictures and architectural underpinnings as your application scales up. In the case of variables, this means that in scripts and modules, lexical variables (à la strict) are the default, but in those -e one-liners the default is package variables. (Rakudo doesn’t implement this distinction yet, and one has to use lexical variables even at the command line. After it’s been implemented in Rakudo, I’d expect the perl6 invocations above to get past compilation, and produce outputs similar to the perl invocations.)

Moving along. At this point you might consider all that’s worth saying about lexical variables to have been said — not so. You see, the result of designing things right is that surprising and awesome bonuses keep falling out. Consider this subroutine:

sub counter($start_value) {
    my $count = $start_value;
    return { $count++ };
}

What’s returned at return { $count++ } is a block of code. So each time we call counter, what we get back is a little disconnected piece of code that can be called, as many times as we want.

Now look what happens when we create two such pieces of code and play around with them:

my $c1 = counter(5);
say $c1();           # 5
say $c1();           # 6

my $c2 = counter(42);
say $c2();           # 42
say $c1();           # 7
say $c2();           # 43

See that? The vital observation here is that $c1 and $c2 are acting entirely independently of each other. Both keep their own state, in the form of the $count variable, and although this might look like the same variable to us, to the two invocations of counter it looks like two different storage locations — because each time we enter a block of code, we start out afresh. The little block of code returned from some run of counter retains a relation to that particular storage location (it “closes over” the storage location, protecting it from the grasp of the Grim Garbage Collector; thus this kind of block is called a closure.)

If closures look a lot like lightweight objects to you, congratulations; they are. The principle behind closures, regulating the way values are accessed, is the same as the principle behind encapsulation and information hiding in OO. It’s all about limiting the extent of things, so that they can wreak as little havoc as possible when things turn ugly.

You can do nifty things like closures with lexical variables. You can’t with package variables. Lexical variables are cooler. QED.

Day 23: Lazy fruits from the gather of Eden

December 23, 2009

Today’s gift is a construct not often seen in other languages. It’s an iterator builder! And it’s called gather.

But first, let’s try a bit of historical perspective. Many Perl people know their map, grep and sort, convenient functions to carry out simple list transformations, filterings and rankings without having to resort to for loops.

my @squares = map { $_ * $_ }, @numbers;
my @primes  = grep { is-prime($_) }, @numbers;

The map and grep constructs are especially powerful once we get comfortable with chaining them:

my @children-of-single-moms =
    map  {  .children },
    grep { !.is-married },
    grep {  .gender == FEMALE },
         @citizens;

(Note that .children may return one child, a list of several children or an empty list. map has a flattening influence on the lists thus produced, so the final result is a flat list of children.)

The chaining of map and sort gave rise to the famous Schwartzian transform, a Perl 5 caching idiom for when the thing being sorted on is computationally expensive:

my @files-by-modification-date =
    map  { .[0] },                # deconstruct
    sort { $^a[1] <=> $^b[1] },
    map  { [$_, $_ ~~ :M] },      # compute and construct
         @files;

It’s unfortunate that the functional paradigm puts the steps in reverse order of processing. The proposed pipe syntax, notably the ==>, would solve that. But it’s not implemented in Rakudo yet, only described in S03.

Anyway, if you’ve read the post from day 20, you know that the Schwartzian transform is built into sort nowadays:

my @files-by-modification-date =
    sort { $_ ~~ :M },
    @files;

So that’s, you know, coming along.

Now, what about this gather construct? Well, it’s a kind of generalization of map and grep.

sub mymap(&transform, @list) {
    gather for @list {
        take transform($_);
    }
};

sub mygrep(&condition, @list) {
    gather for @list {
        take $_ if condition($_);
    }
};

(The real map can swallow several argument at a time, making it more powerful than the &mymap above.)

Just to be clear about what happens: gather signals that within the subsequent block, we’ll be building a list. Each take adds an element to the list. You could think of it as pushing to an anonymous array if you want:

my @result = gather { take $_ for 5..7 }; # this...

my @result;
push @result, $_ for 5..7; # ...is the same as this

Which brings us to the first property of gather: it’s the construct you can use for building lists when map, grep and sort aren’t sufficient. Of course, there’s no need to reinvent those constructions… but the fact that you can do that, or roll your own special variants, is kinda nice.

sub incremental-concat(@list) {
  my $string-accumulator = "";
  gather for @list {
    # RAKUDO: The ~() is a workaround for [perl #62178]
    take ~($string-accumulator ~= $_);
  }
};

say incremental-concat(<a b c>).perl; # ["a", "ab", "abc"]

The above is nicer than using map, since we need to manage the $string-accumulator between iterations.

(Implementing &incremental-concat by hand is silly in an implementation which implements the [\~] operator. Just a short announcement to people who want to keep track of the extent to which Perl 6 is channeling APL. Rakudo doesn’t yet, though.)

The second property of gather is that while the take calls (of course) have to occur within the scope of a gather block, they do not necessarily have to occur in the lexical scope, only the dynamic scope. For those unfamiliar with the distinction, I think an example explains it best:

sub traverse-tree-inorder(Tree $t) {
  traverse-tree-inorder($t.left) if $t.left;
  take transform($t);
  traverse-tree-inorder($t.right) if $t.right;
}

my $tree = ...;
my @all-nodes = gather traverse-tree-inorder($tree);

See what’s happening here? We wrap the call to &traverse-tree-inorder in a gather statement. The statement itself doesn’t lexically contain any take calls, but the called subroutine does, and the take in there remembers that it’s in a gather context. That’s what makes the gather context dynamic rather than lexical.

Just to hammer in the point, traverse-tree-inorder does lexical recursion on a tree structure, and no matter how far down the call stack we find ourselves, the values passed to take find their way back into the same anonymous array, rooted in the gather around the original call. It’s as if the anonymous array were implicitly passed around for us automatically as invisible arguments. Another way to view it is that the gather mode works orthogonally to the call stack, essentially not caring about how many calls down it is.

Should we be unfortunate enough to do a take outside of any gather block, we’ll get a warning at runtime.

I’ve saved the best till last: the third property of gather: it’s lazy.

What does “lazy” mean here? Well, to take the above tree-traversing code as an example: when the assignment to @all-nodes has executed, the tree hasn’t yet been traversed. Only when you access the first element of the array, @all-nodes[0], does the traversal start. And it stops right after it finds the leftmost leaf node. Access @all-nodes[1], and the traversal will resume from where it left off, run just enough to find the second node in the traversal, and then stop.

In short, the code within the gather block starts and stops in such a way that it never does more work than you’ve asked it to do. That’s lazy.

It’s essentially a model of delayed execution. Perl 6 promises to run the code inside your gather block, but only if it turns out that you actually need the information. Operationally, you can think of it as a separate thread that starts and stops, always doing the smallest possible amount of work to keep the main thread satisfied. But under the hood in a given implementation, it’s likely implemented by continuations — or, failing that, by painful, complicated cheating.

Now here’s the thing: most any array in Perl 6 has the lazy behavior by default, and things like reading all lines from a file are lazy by default, and not only can map and grep be implemented using gather; it turns out that they actually are, too. So map and grep are also lazy.

Now, it’s nice to know that values aren’t unnecessarily generated when you’re doing calculations with arrays… but the really nice thing is that lazy arrays open up the door for stream-based programming and, by extension, infinite arrays.

Unfortunately, laziness hasn’t landed in Rakudo yet. We’re nearly there though, so I don’t feel too bad dangling these examples in front of you, even though they will currently cause Rakudo to spin the fans of your computer and nothing more:

my @natural-numbers = 0 .. Inf;

my @even-numbers  = 0, 2 ... *;    # arithmetic seq
my @odd-numbers   = 1, 3 ... *;
my @powers-of-two = 1, 2, 4 ... *; # geometric seq

my @squares-of-odd-numbers = map { $_ * $_ }, @odd-numbers;

sub enumerate-positive-rationals() { # with duplicates, but still
  take 1;
  for 1..Inf -> $total {
    for 1..^$total Z reverse(1..^$total) -> $numerator, $denominator {
      take $numerator / $denominator;
    }
  }
}

sub enumerate-all-rationals() {
  map { $_, -$_ }, enumerate-positive-rationals();
}

sub fibonacci() {
  gather {
    take 0;
    my ($last, $this) = 0, 1;
    loop { # infinitely!
      take $this;
      ($last, $this) = $this, $last + $this;
    }
  }
}
say fibonacci[10]; # 55

# Merge two sorted (potentially infinite) arrays
sub merge(@a, @b) {
  !@a && !@b ?? () !!
  !@a        ?? @b !!
         !@b ?? @a !!
  (@a[0] < @b[0] ?? @a.shift !! @b.shift, merge(@a, @b))
}

sub hamming-sequence() # 2**a * 3**b * 5**c, where { all(a,b,c) >= 0 }
  gather {
    take 1;
    take $_ for
        merge( (map { 2 * $_ } hamming-sequence()),
               merge( (map { 3 * $_ }, hamming-sequence()),
                      (map { 5 * $_ }, hamming-sequence()) ));
  }
}

(That last subroutine is a Perl 6 solution to the Hamming problem, described in section 6.4 of mjd++’s Higher Order Perl. A seriously cool book, by the way. It builds iterators from scratch; we just use gather for the same result.)

Today’s obfu award goes to David Brunton, who has written a Perl 6 tweet which draws a rule #30 cellular automaton, which also happens to look like a Christmas tree.

$ perl6 -e 'my %r=[^8]>>.fmt("%03b") Z (0,1,1,1,1,0,0,0);\
say <. X>[my@i=0 xx 9,1,0 xx 9];\
for ^9 {say <. X>[@i=map {%r{@i[($_-1)%19,$_,($_+1)%19].join}},^19]};'
.........X.........
........XXX........
.......XX..X.......
......XX.XXXX......
.....XX..X...X.....
....XX.XXXX.XXX....
...XX..X....X..X...
..XX.XXXX..XXXXXX..
.XX..X...XXX.....X.
XX.XXXX.XX..X...XXX

Day 16: We call it ‘the old switcheroo’

December 16, 2009

Another glorious day in Advent; another gift awaits us. It’s switch statements!

Well, the term for them is still “switch statement” in Perl 6, but the keyword has changed for linguistic reasons. It’s now given, as in “given today’s weather”:

given $weather {
  when 'sunny'  { say 'Aah! ☀'                    }
  when 'cloudy' { say 'Meh. ☁'                    }
  when 'rainy'  { say 'Where is my umbrella? ☂'   }
  when 'snowy'  { say 'Yippie! ☃'                 }
  default       { say 'Looks like any other day.' }
}

Here’s a minimal explanation of the semantics, just to get us started: in the above example, the contents of the variable $weather is tested against the strings 'sunny', 'cloudy', 'rainy', and 'snowy', one after the other. If either of them matches, the corresponding block runs. If none matches, the default block triggers instead.

Not so different from switch statements in other languages, in other words. (But wait!) We’ll note in passing that the when blocks don’t automatically fall through, so if you have several conditions which would match, only the first one will run:

given $probability {
  when     1.00 { say 'A certainty'   }
  when * > 0.75 { say 'Quite likely'  }
  when * > 0.50 { say 'Likely'        }
  when * > 0.25 { say 'Unlikely'      }
  when * > 0.00 { say 'Very unlikely' }
  when     0.00 { say 'Fat chance'  }
}

So if you have a $probability of 0.80, the above code will print Quite likely, but not Likely, Unlikely etc. (In the cases when you want to “fall through” from a when block, you can end it with the keyword continue.) (Update: after spec discussions that originated in the comments of this post, break/continue were renamed to succeed/proceed.)

Note that in the above code, strings and decimal numbers and comparisons are used as the when expression. How does Perl 6 know how to match the given value against the when value, when both can be of wildly varying types?

The answer is that the two values enter a negotiation process called smartmatching, mentioned briefly in Day 13. To summarize, smartmatching (written as $a ~~ $b) is a kind of “regex matching on steroids”, where the $b doesn’t have to be a regex, but can be of any type. For ranges, the smartmatch will check if the value we want to match is within the range. If $b is a class or a role or a subtype, the smartmatch will perform a type check. And so on. For values like Num and Str which represent themselves, some appropriate equivalence check is made.

The “whatever star” (*) has the peculiar property that it smartmatches on anything. Oh, and default is just sugar for when *.

To summarize the summary, smartmatching is DWIM in operator form. And the given/when construct runs on top of it.

Now for something slightly head-spinning: the given and when features are actually independant! While you complete the syllable “WHAT?”, let me explain how.

Given is actually a sort of once-only for loop.

given $punch-card {
  .bend;
  .fold;
  .mutilate;
}

See what happened there? All given does is set the topic, also known to Perl people as $_. The cute .method is actually short for $_.method.

Now it’s easier to see how when can be used without a given, too. when can be used inside any block which sets $_, implicitly or explicitly:

my $scanning;
for $*IN.lines {
  when /start/ { $scanning = True }
  when /stop/  { $scanning = False }

  if $scanning {
    # Do something which only happens between the
    # lines containing 'start' and 'stop'
  }
}

Note that those when blocks exhibit the same behaviour as the in a given block: they skip the rest of the surrounding block after executing, which in the above code means they go directly to the next line in the input.

Here’s another example, this time with $_ explicitly set:

sub fib(Int $_) {
  when * < 2 { 1 }
  default { fib($_ - 1) + fib($_ - 2) }
}

(This independence between given and when plays out in other ways too. For example, the way to handle exceptions is with a CATCH block, a variant of given which topicalizes on $!, the variable holding the most recent exception.)

To top it all off, both given and when come in statement-ending varieties, just as for, if and the others:

  say .[0] + .[1] + .[2] given @list;
  say 'My God, it's full of vowels!' when /^ <[aeiou]>+ $/;

You can even nest a when inside a given:

  say 'Boo!' when /phantom/ given $castle;

As given and when represent another striking blow against the Perl obfuscation track record, I hereby present you with the parting gift of an obfu DNA helix, knowing full well that it doesn’t quite make up for the damage caused. :)

$ perl6 -e 'for ^20 {my ($a,$b)=<AT CG>.pick.comb.pick(*);\
  my ($c,$d)=sort map {6+4*sin($_/2)},$_,$_+4;\
  printf "%{$c}s%{$d-$c}s\n",$a,$b}'
     G  C
      TA
     C G
   G    C
 C     G
 G     C
 T   A
  CG
 CG
 C   G
 T     A
  T     A
   T    A
     C G
      TA
    T   A
  T     A
 A     T
 C    G
 G  C

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 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 44 other followers