Archive for the ‘2010’ Category

Merry Christmas!

December 25, 2010

The people who brought you this year’s Advent Calendar had a blast doing so — it’s exciting to get to present new and old Perl 6 features to new and old readers. Thanks everyone! And Merry Christmas!

Day 1 – Reaching the Stars
Day 2 – Interacting with the command line with MAIN subs
Day 3 – File operations
Day 4 – The Sequence Operators
Day 5 – Why Perl syntax does what you want
Day 6 – The X and Z metaoperators
Day 7 – Lexical variables
Day 8 – Different Names of Different Things
Day 9 – The module ecosystem
Day 10 – Feed operators
Day 11 – Markov Sequence
Day 12 – Smart matching
Day 13 – The Perl6 Community
Day 14 – nextsame and its cousins
Day 15 – Calling native libraries from Perl 6
Day 16: Time in Perl6
Day 17 – Rosetta Code
Day 18 – ABC Module
Day 19 – False truth
Day 20 – The Perl 6 Synopses
Day 21 – transliteration and beyond
Day 22 – The Meta-Object Protocol
Day 23 – It’s some .sort of wonderful.
Day 24 – Yule the Ancient Troll-tide Carol
Day 25 – Merry Christmas!

Day 24 – Yule the Ancient Troll-tide Carol

December 24, 2010

When you open your gift on Christmas Eve, you discover a mirror in which you can see yourself. On the mirror is etched the statement:

    SUBJECTS IN MIRROR ARE CLOSER THAN THEY APPEAR

It doesn’t look at all like a car mirror though. It seems quite flimsy, in fact, though it’s made of some rather tough material that seems to defy breakage despite your best efforts as a two-year old…

“WTF? How did the mirror show me a picture of my younger self?”

You bend the mirror this way and that, and it shows you not just embarrassing views of yourself in the past, but also pictures of yourself as you might be someday in the future, both good and bad.

“Whoa!”

Suddenly you feel a strong tug on your innards, and your vision shifts; instead of looking at the mirror from the outside, you’re looking at it from the inside. You can still see all the same reflections of yourself, but you also see other people, still outside the mirror, looking in at you as a picture of their own younger or older self.

Apparently, you’ve been sucked into a hyper-mirror, in an accidental sort of way.

You are now a member of the Perl 6 community. We (including you) will now give you (including us) the gift of ourselves as we would like to be someday.

In other words, you have been hacked! Borged, even! But you might learn to like it.

Perl is not just a technology; it’s a culture. Just as Perl is a technology of technological hacking, so too Perl is a culture of cultural hacking. Giving away a free language implementation with community support was the first cultural hack in Perl’s history, but there have been many others since, both great and small. You can see some of those hacks in that mirror you are holding.  Er…that is holding you.

The second big cultural hack was demonstrating to Unix culture that its reductionistic ideas could be subverted and put to use in a non-reductionistic setting. Dual licensing was a third cultural hack to make Perl acceptable both to businesses and the FSF. Yet another well-known hack was writing a computer book that was not just informative but also, gasp, entertaining! But these are all shallow hacks. The deep hack was to bootstrap an entire community that is continually hacking on itself recursively in a constructive way (well, usually).

Perl 6 continues this fine tradition of “positive trolling”. You know, in the olden days you could say “troll” to mean something happy and boisterous, as in “troll the ancient yuletide carol”. That’s the kind of trolling we do, especially here in the Advent Calendar (one of the finest examples of the community recursively constructing itself). There are many other examples as well.

If you look at perl6.org, you will see several cultural hacks right there on the front page. The most obvious one is the butterfly, Camelia, but she represents a number of other hacks through image and words. As an image, she says:

  • Perl 6 is fun.
  • Perl 6 is organic.
  • Perl 6 is attractive.
  • Perl 6 is about clarity.
  • Perl 6 is personal and relational.
  • Perl 6 is a result of metamorphosis.
  • Perl 6 is both primitive and elaborate.
  • Perl 6 is friendly to women and children.

On the flip side, the image also says:

  • Perl 6 is not about sterile corporate image.
  • Perl 6 is not achingly beautiful, just pretty.
  • Perl 6 is not ill-behaved like a camel.
  • Perl 6 is not friendly to grinches.

It is on this visceral level that Camelia has turned out to be a most useful cultural hack, that tells us with a fair degree of certainty who the grinches are who want to steal Christmas. Every community has to deal with an influx of potentially poisonous people, and having an obvious target like Camelia to complain about induces such people to wave a flag reading: “Hey, I’m a troll. Hug me.”

And that’s another cultural hack in the Perl 6 community. We believe in hugging trolls. Up to a point.

You can see this in Camelia’s words, when she says you can participate only if “you know how to be nice to all kinds of people”. Trolls are people too, and we know how to be nice to them. (When we are not nice to trolls, it’s because we decided not to be, not because we don’t know how.)

You see, some of us were trolls once too. As in our mirror metaphor above, we are all looking at each other as we travel together in our journey through life. Many of us hope to end up better people than we are today; we also realize we were worse people in the past. But there are many people who have not made that commitment yet to get better. Some of these uncommitted folks are currently trolls. Some trolls are evil, but many are simply ignorant of a better way.

So when we say we hug trolls, what we really mean in technical terms is that we don’t pay much attention to your position when you join us, however odious that position might be. Instead, we look at the first and second derivatives of your position. To give us time to differentiate, we typically perform a bit of verbal aikido to let you express some of your deeper yearnings while you think you are merely tormenting us.

If your position is bad but your velocity seems to be good, we will certainly try to keep you around until your position is good as well. You want to be good. We can help with that.

If your position is bad, and your velocity is bad, then we’ll look for signs that your velocity might be getting less bad, which is to say you have a positive acceleration. You don’t yet want to be good, but perhaps you want to want to. We may be able to help with that too. If the acceleration stays positive, eventually the velocity and position will come around too.

In short, there are grinches, but some grinches will repent. We want to give them the chance. Sometimes this involves singing when the grinch steals all the presents.

But some of you grinches will never repent. Did we mention that Camelia has a 3-meter wingspan? And that she likes to suck the brains from unrepentant grinches? Not only that, but Camelia’s larval form was a camel, so she can spit too. You really, really don’t want to have Camelia sucking your brain and then spitting.

But most people don’t need to have their brains either sucked or spat. Often they just need them washed. Once people catch on to the meta-philosophy of Perl, they usually find the search for technical and cultural convergence to be a Great Adventure, and much more fun than simply making people unhappy, which is too easy.

We hope you like your new hyper-mirror, and we hope you’ve enjoyed (or will enjoy) reflecting on some of these posts. Please have a Great Advent to a Great Adventure.

Fa la la!

Day 23 – It’s some .sort of wonderful.

December 23, 2010

Continuing on our Perl 6 adventure.

Sorting various lists of things is an extremely common programming task, and Perl 6 beefs up its sort function to help you get it done.

It has your everyday, garden variety sort:

    # default type sensitive sort
    my @sorted = @unsorted.sort; # or sort @unsorted;

And, like Perl 5, allows you to use custom comparator functions:

    # numeric comparison
    my @sorted = @unsorted.sort: { $^a <=> $^b };

    # or if you prefer to use function calling semantics
    my @sorted = sort { $^a <=> $^b }, @unsorted;

    # string comparison ( similar to Perl 5 cmp )
    my @sorted = @unsorted.sort: { $^a leg $^b };

    # type dependent comparison
    my @sorted = @unsorted.sort: { $^a cmp $^b };

These can also be written with parenthesis around the comparator, in which case you don’t need the colon. Handy for when you want to chain other methods after the sort:

    my @topten = @scores.sort( { $^b <=> $^a } ).list.munch(10);
A Small Aside… In Perl 6 the variables $a and $b don’t have any special global significance like they do in Perl 5. Use normal named variables ($var), positional variables ($^var) or whatever variables (*) in the sort comparison block just like any other code block.

You can directly apply a transform function as you sort:

    my @sorted = @unsorted.sort: { foo($^a) cmp foo($^b) };

but the foo() transform is being calculated anew for each iteration of the sort comparison. Probably not too bad for small lists, but can be a real drag as the lists get larger, especially if foo() is computation intensive.

A common idiom in Perl 5 is to use a Schwartzian Transform when you want to sort on some transformation of terms rather than the terms themselves.

When you use a Schwartzian Transform, each transform is calculated once, the items are sorted by the transformed terms, then the original terms mapped back and returned in the new order.

    # Perl 5 code
    @sorted =
        map  { $_->[0] }
        sort { $a->[1] cmp $b->[1] }
        map  { [$_, foo($_)] }
        @unsorted;

In Perl 6 you can still do a Schwartzian Transform, but there is some special intelligence built in to sort. If you have a transform function with arity 0 or 1, ( arity is the number of arguments that the function takes ), Perl 6 notices and will automatically apply a Schwartzian Transform for you.

Lets take a look at a few examples.

Sort Case Insensitively

Lowercase each term, sort on the lowercased terms then return the original terms in the lowercased sort order.

   my @sorted = @unsorted.sort: { .lc };

Pretty easy.

Sort By Word Length

Sort a list of strings by the number of characters in each string shortest to longest:

    my @sorted = @unsorted.sort: { .chars };

Or longest to shortest:

    my @sorted = @unsorted.sort: { -.chars };

Multiple Sort Comparators

You can pass a list of comparator functions in the sort block and it will perform as many comparator transforms in the list as necessary until it reaches a tie breaker:

Sort by word length with a secondary ASCII sort so that each group of words with the same length are then sorted in ASCII order:

     .say for @a.sort: { $^a.chars, $^a } ;

Except… that doesn’t quite work yet in Rakudo. It compares the word lengths string-wise rather than numerically, so 10 and 11 are sorted before 2. :-( BUT!! As the saying goes: TIMTOWDI! ( There Is More Than One Way to Do It!)

Sort is stable in Perl 6, so you can sort the list to get it into ASCII order, then re-sort it with the length comparator:

     .say for @a.sort.sort: { $^a.chars };

That works, but now it is sorting twice. Not too efficient. Or you could rewrite it like:

     .say for @a.sort: { $^a.chars <=> $^b.chars || $^a leg $^b };

That also works, but now you’ve lost the automatic Schwartzian Transform. ( arity 2 comparator )

Or, you could apply a natural sorting transform to the numeric terms to get the correct answer.

     .say for @a.sort: { $^a.chars.&naturally, $^a };

“Natural Sorting!?”, I hear you cry, “Where’d that come from?”.

I’m glad you asked.

Let’s take a ride on that segue.


Natural Sorting

Standard lexical sorting returns items in “ASCIIbetical” order. Digits sort before upper case characters and both sort before lower case characters. People are often surprised / dismayed when they sort a list of strings and get something like:

    0
    1
    100
    11
    144th
    2
    21
    210
    3rd
    33rd
    AND
    ARE
    An
    Bit
    Can
    and
    by
    car
    d1
    d10
    d2

Which is perfectly correct, but not very intuitive for humans, especially for non-programmers.

“Natural” sorting would order numbers (strings of digits) sorted by order of magnitude then by magnitude before alphabetical position (upper or lower case).

Here is the same group of strings shown above sorted naturally:

    0
    1
    2
    3rd
    11
    21
    33rd
    100
    144th
    210
    An
    AND
    and
    ARE
    Bit
    by
    Can
    car
    d1
    d2
    d10

To do that, we want a simple transform we can apply to each term.

I’ll use a subst method. It an analogue of the familiar s/// operator in method form.

    .subst(/(\d+)/, -> $/ { 0 ~ $0.chars.chr ~ $0 }, :g)

In the first part we are capturing a group of one or more consecutive digits to operate on. That ‘ -> $/ { … } ‘ construct is a “pointy block”. It means: “Expose the contents of the match array ( $/ ) to the inner scope of the following block of code ( {…} )”. The block builds the replacement string: ’0′ concatenated with the order of magnitude of (number of digits in) the group, expressed as an ASCII character, concatenated with the original string of digits. The :g adverb means “do it globally”.

We also want to sort case insensitively so we’ll chain a .lc method in and get:

    .lc.subst(/(\d+)/, -> $/ { 0 ~ $0.chars.chr ~ $0 }, :g)

Turn it into a subroutine:

    sub naturally ($a) {
        $a.lc.subst(/(\d+)/, -> $/ { 0 ~ $0.chars.chr ~ $0 }, :g)
    }

This works fairly well but has a subtle bug. Terms that map to the same transform will be returned in the order they were seen. So, for instance, the words; ‘THE’, ‘The’ and ‘the’ will return in the order seen in the list rather than some predictable sorted order. A simple solution is to just concatenate the original term to the end of the transformed term to act as a tie breaker.

So the final naturally() transform routine looks like:

    sub naturally ($a) {
        $a.lc.subst(/(\d+)/, -> $/ { 0 ~ $0.chars.chr ~ $0 }, :g) ~ "\x0" ~ $a
    }

Since it operates on a single term at a time, we get the Schwartzian Transform for free. Now we can use it as a sort modifier to naturally sort a list of words:

    .say for <0 1 100 11 144th 2 21 210 3rd 33rd AND ARE An Bit Can and by car d1 d10 d2>.sort: { .&naturally };

Or to sort a list of dotted quad notation IP addresses:

     # generate a list of random IPs
     my @ips = ((0..255).roll(4).join('.')for 0..99);

    .say for @ips.sort: { .&naturally };

    4.108.172.65
    5.149.121.70
    10.24.201.53
    11.10.90.219
    12.83.84.206
    12.124.106.41
    12.162.149.98
    14.203.88.93
    16.18.0.178
    17.68.226.104
    21.201.181.225
    23.61.166.202
    23.205.73.104
    24.250.90.75
    35.56.124.120
    36.158.70.141
    40.149.118.209
    40.238.169.146
    52.107.62.129
    55.119.95.120
    56.39.105.245
    ... and so on

Or to sort directory listings, or anything else that contains a mixture of alphanumeric characters… or even to work around bugs. ;-)

Merry Christmas, Happy sorting, and

May the Schwartz be with you!

Day 22 – The Meta-Object Protocol

December 22, 2010

Have you ever wondered how to create a class in your favorite programming language, not by writing a class definition, but by running some code? Some languages allow that by simple API calls. The API behind it is called the Meta-Object Protocol, short MOP.

Perl 6 has a MOP, and it allows you to create classes, roles and grammars, add methods and attributes, and to introspect classes. For example we can use calls to the MOP in Rakudo to find out how the Rat type (rational numbers) is implemented. Calls to methods of the MOP generally start with .^ instead of just .:

 $ perl6
 > say join ', ', Rat.^attributes
 $!numerator, $!denominator
 > # the list of all methods is a bit long,
 > # so here is a random selection
 > say join ', ', Rat.^methods(:local).pick(5)
 unpolar, ceiling, reals, Str, round
 > say Rat.^methods(:local).grep('log').[0].signature.perl
 :(Numeric $x: Numeric $base = { ... };; *%_)

Most of these lines should be fairly self-explanatory: objects of class Rat has two attributes, $!numerator and $!denominator, as well as many methods. The log method takes a Numeric value as invocant (marked by the colon after the parameter name), and an optional second parameter called $base, which has a default value (but which Rakudo can’t show you. It’s Euler’s number).

A nice use case comes from the Perl 6 database interface. It has the option to log calls on an object, and to restrict this to only log methods from a certain role (for example only a role related to connection management, or related to data retrieval). Here is the example, and a possible way to call it:

 sub log-calls($obj, Role $r) {
     my $wrapper = RoleHOW.new;
     for $r.^methods -> $m {
         $wrapper.^add_method($m.name, method (|$c) {
             # print logging information
             # note() writes to standard error
             note ">> $m";
             # call the next method of the same name,
             # with the same arguments
             nextsame;
         });
     }
     $wrapper.^compose();
     # the 'does' operator works just like 'but', but
     # only modifies a copy of the object
     $obj does $wrapper;
 }
 role Greet {
     method greet($x) {
         say "hello, $x";
     }
 }
 class SomeGreeter does Greet {
     method LOLGREET($x) {
         say "OH HAI "~ uc $x;
     }
 }
 my $o = log-calls(SomeGreeter.new, Greet);
 # logged, since provided by role Greet
 $o.greet('you');
 # not logged, because not provided by the role
 $o.LOLGREET('u');

Output:

 >> greet
 hello, you
 OH HAI U

So with a Meta-Object Protocol, classes, roles and grammars are not just accessible by special syntax, but can be accessed as a normal API. This gives new flexibility to object oriented code, and allows easy introspection and modification of objects.

Day 21 – transliteration and beyond

December 21, 2010

Transliteration sounds like it has Latin roots and means a changing of letters. And that’s what the Str.trans method does.

say "GATTACA".trans( "TCAG" => "0123" );  # prints "3200212\n"

Perl 5 people (and Unix shell folk) immediately recognize this as tr/tcag/0123/, but here’s a quick explanation for the rest of you out there: for every instance of T we find in the string, we replace it by 0, we replace every instance of C by 1, and so on. The two strings TCAG and 0123 supply alphabets to be translated to and from, respectively.

This can be used for any number of time-saving ends. Here, for example, is a simple subroutine that “encrypts” a text with ROT-13:

sub rot13($text) { $text.trans( "A..Za..z" => "N..ZA..Mn..za..m" ) }

When .trans sees those .. ranges, it expands them internally (so "n..z" really means "nopqrstuvwxyz"). Thus, the ultimate effect of the rot13 sub is to map certain parts of the ASCII alphabet to certain other parts.

In Perl 5, the two dots (..) are a dash (-), but we’ve tried in Perl 6 to have those two dots stand for the concept “range”; in the main language, in regexes, and here in transliterations.

Note also that the .trans method is non-mutating; it doesn’t change $text, but just returns a new value. This is also a general theme in Perl 6; in the core language we prefer to offer the side-effect-free variants of methods. You can easily get the mutating behavior by doing .=trans:

$kabbala.=trans("A..Ia..i" => "1..91..9");

(And that goes not only for .trans, but for all methods. It’s a silent encouragement to you as a programmer to write your libraries with non-mutating methods, making the world a happier, more composable place.)

But Perl 6 wouldn’t be Perl 6 if .trans didn’t also contain a hidden weapon which takes the Perl 5 tr/// and just completely blows it out of the water. Here’s what it also does:

Let’s say we want to escape some HTML, that is, replace things according to this table:

    & => &amp;
    < => &lt;
    > => &gt;

(By the way, I hope if you ever need to escape HTML, that there will be a library routine for you ready that does it for you. But the general principle is important; and in the few instances when you do need to do something like this, it’s good to know the tools are there, built into the language.)

This is nothing that a few well-placed regexes can’t handle. So what’s the big deal? Well, a naive in-place per-match replacement of the above three characters might be unlucky enough to get stuck in an infinite loop. (& => &amp; => &amp;amp; => ...) So you need to do various sordid trickery to avoid that.

But that’s not even the fundamental problem, which is that you want to resort to stitching together pieces of strings, rather than thinking of the problem in a more high-level manner. Generally, we wouldn’t want a solution that depends on the order of the substitutions. That would also affect something like this:

    foo         => bar
    foolishness => folly

If the former substitution is attempted first each time, there won’t ever be an occasion to perform the latter one — probably not what was intented. Generally, we want to try and match the longer substrings before shorter ones.

So, it seems we want a longest-token substitution matcher that avoids infinite cycles due to accidental re-substitution.

That’s what .trans in Perl 6 provides. That’s its hidden weapon: sending in a pair of arrays rather than strings. For the HTML escaping, all we need to do is this:

my $escaped = $html.trans(
    [ '&',     '<',    '>'    ] =>
    [ '&amp;', '&lt;', '&gt;' ]
);

…and the non-trivial problems of replacing things in the right order and avoiding cyclical replacement are taken care of for us.

Day 20 – The Perl 6 Synopses

December 20, 2010

The tag line for this blog is “Something cool about Perl 6 every day” and today I’m going to talk about something I think is very cool—the Synopses.

First, a quick background. When Perl 6 was first announced in 2000, the community didn’t quite know what needed to be done. So a requests for comments (RFC) process was started and resulted in over 360 RFCs that suggested changes to Perl. From these RFCs Larry Wall synthesized the Apocalypses which sought to reveal the design of the language. Later, Damian Conway created the Exegeses which showed how the design could be used in practice.

Fast forward to the present day. There are several implementations of Perl 6 out there and each has their own implementation focus. One has prioritized the object model, another the parsing engine, a third has prioritized implementing the bulk of the basic Perl 6 syntax. How do each of these implementations maintain their “Perl-6-ness” while still focusing on their particular implementation niche?

The answer is the Synopses. These documents are the official Perl 6 specification. Each Synopsis covers a specific topic within the Perl 6 language that somewhat mirrors chapters in “Programming Perl” (the camel book).

What if you think you’ve found a bug in an implementation? How do you know it’s a bug? Consult the relevant Synopsis. As far as the Perl 6 community goes, what’s written in the Synopses is definitive.

What if you think there’s a bug in a Synopsis or that it contradicts another Synopsis? Either send a message to perl6-language@perl.org or drop by #perl6:irc.freenode.net to discuss it. Because here’s the other cool thing about these Synopses … they are living documents. When there is a contradiction or just something that needs clarification, talking about it with #perl6 is often all it takes to get the problem fixed. Actually, just mentioning your trouble in a public forum of some sort (twitter, a blog, etc.) is likely to garner enough attention. There are no layers of beaurocracy to navigate in order to affect change.

Now, this last thing may seem slightly bizarre, but … almost anyone can edit the Synopses. They aren’t held fixed by some divine power. All it takes is active participation in the Perl 6 discussion. There is a price for this ability however–your changes must withstand the scrutiny of the Perl 6 community. Much like a wiki, social pressures and an active community are used to maintain the integrity of the Synopses.

Day 19 – False truth

December 19, 2010

Today’s advent gift teaches us how to use mixins for nefarious and confusing purposes. In fact, this feature will probably appear partly insane, but it turns out to be quite useful. Enter the but operator:

my $value = 42 but role { method Bool  { False } };
say $value;    # 42
say ?$value;   # False

So you see, we overload the .Bool method on our $value. It doesn’t affect other integers in the program, not even other 42s in the program, just this one. Normally, for Ints, the .Bool method (and therefore the prefix:<?> operator) returns whether the number is non-zero, but here we make it always return False.

In fact, there’s a shorter way to write this for enum values, of which False is one.

my $value = 42 but False;

Since False is a value of the Bool type, it will automatically overload the .Bool method, which by convention is a kind of conversion method in Perl 6. Values of other types will of course overload their corresponding conversion method.

Here’s the part that turns out to be quite useful: in Perl 5 when you put a &system call in an if statement wanting to check for success, you have to remember to negate the result of the call, since in bash only zero means success:

if ( system($cmd) == 0 ) {  # alternatively, !system($cmd) 
    # ...
}

But in Perl 6, the corresponding &run routine returns the above kind of overloaded integers; these boolify to True if and only if the return value is zero, which is the opposite of the default Int behavior, and just what we need.

if run($cmd) {  # we don't negate
    # ...
}

Oh, and here’s the part that appears insane. :-) We can overload the .Bool method of boolean values!

my $value = True but False;
say $value;    # True
say ?$value;   # False

Yes, Perl 6 allows you to shoot yourself in the foot in this particular way. Though I don’t see why anyone would want to do this except for obfuscatory purposes, I’m kinda glad Perl 6 has the presence of mind to keep track of the subtleties of that type of overloading. I know I almost don’t. :-)

Day 18 – ABC Module

December 18, 2010

Instead of focusing on a particular feature of Perl 6 today, I’d like to take you on a quick tour of the ABC module. I think it’s a nice example of some of the strengths of Perl 6.

ABC Notation is a simple text file format designed to make it easy to support musical notation. It’s widely used in the world of traditional dance music because it is very lightweight and more than powerful enough to support notating jigs and reels. Here’s an example in honor of the season:

X:1
T:While Shepherds Watched Their Flocks
M:5/4
L:1/4
O:Green's Harbour, Newfoundland
K:A major
E|:[M:5/4] A A/B/ B2 A|B c/B/ A2 A/B/|
[M:6/4]c d/c/ B2 B2|[M:4/4] A3 E|AB AG|
FE FE|AB AG|F2 F2|E2 G2|A/G/ F/E/ DF|
[1 [M:6/4] E C/B,/ A,3 E:|[2 [M:5/4] E C/B,/ A,3|]

I won’t get into the details — here’s a tutorial if you’d like to know more — but the structure of the file is simple. The first section is the header, with general information about the tune. The remainder is the tune itself. This one is a bit more complicated than many because of all the embedded time signature changes, like [M:6/4].

I was always surprised there wasn’t a CPAN module for handling ABC notation, and even seriously considered writing one myself at one point. But parsing ABC is a complicated process, and I gave up in frustration before getting very far.

Enter Perl 6 and its grammars. About 60 lines of simple regexes is all that is needed to parse most of the tunes I am interested in. (Several of the more complicated features of ABC, like lyrics and multi-staff music are not implemented yet.) Here’s a snatch of it:

    regex basenote { <[a..g]+[A..G]> }
    regex octave { "'"+ | ","+ }
    regex accidental { '^' | '^^' | '_' | '__' | '=' }
    regex pitch { <accidental>? <basenote> <octave>? }

Compare that to the model BNF grammar for ABC:

basenote ::= %x43 / %x44 / %x45 / %x46 / %x47 / %x41 / %x42 / %x63 / %x64 / %x65 / %x66 / %x67 / %x61 / %x62 ; CDEFGABcdefgab
octave ::= 1*"'" / 1*"," 
accidental ::= "^" / "^^" / "_" / "__" / "=" 
pitch ::= [accidental] basenote [octave]

It’s clearly a very straightforward translation process.

By default, parsing with a Perl 6 grammar just gives you a basic Match object. Adding an object to specify actions to go with the grammar allows you to easily process the information as it is parsed. A simple example is

    method rest($/) {
        make ABC::Rest.new(~$<rest_type>, 
                           $<note_length>.ast);
    }

Whenever the rest regex fires, it returns a new ABC::Rest object. The constructor is passed the string form of the rest_type regex, and an ABC::Duration object created by the action for note_length.

Speaking of durations, another feature of Perl 6 comes very handy here. Durations are represented exactly using the rational number Rat type. If we didn’t have them available, we’d have to code up something similar by hand in order to handle things like triplets whose durations cannot be exactly represented by a floating point number.

So far there is only one significant application using these tools — the abc2ly.pl script included in the ABC module. It converts ABC files to the Lilypond music notation format. Lilypond is a very powerful open source music notation system which produces gorgeous sheet music output. This is a great way to print out good looking music notation from ABC files. (I know there is an abc2ly program included with Lilypond, but last time I checked its output looked tragically bad. abc2ly.pl is already working well enough that I’m hoping to produce a book of sheet music using it in 2011.) So let me leave you with the PDF of the above carol, produced using these tools, Rakudo Perl 6, and Lilypond.

Day 17 – Rosetta Code

December 17, 2010

Do you know what a program chrestomathy is? How about a phrasebook? Or a cribsheet? What about the Rosetta Stone?

RosettaCode.org is much like any of those, though it focuses primarily on programming languages. It’s organized as hundreds of ‘tasks’, which are roughly problem statements, and each task is shown with implementations in many languages.

The gist? Let’s say you know how to do something in language A, and want to see how to do it in language B. By comparing A and B across enough problems, you will start to get a feel for language B’s syntax, and how it relates to the language you’ve come from. Then you’ll notice recurring design patterns and behaviors–the language’s idioms. You’ll be able to see where these are similar to habits you already have, and you’ll be able to see where your existing habits might be get in your way.

Enough preamble. Allow me to direct your attention to a specific places on the site. The topic here isn’t Rosetta Code, really, but how it can help you with Perl 6.

First, there’s a list of all tasks on Rosetta Code which have Perl 6 implementations. Here are a few examples:

Of course, we can’t talk about these kinds of lists of programs without touching on some classics, can we?

As I write this, there are 243 examples of Perl 6 code on the site. If I were to link to all the cases I think you might find interesting, this post would be a link-bomb of amazing proportion. However, allow me to throw one more link at you.

I’ve already given you a link to an index of all 243 of the existing Perl 6 code on the site. As I write this, though, there are 449 tasks. If you’d like to fill in some of the gap…

Day 16: Time in Perl6

December 16, 2010

It’s the 0x10th day of Christmas, and it’s time for you to learn of time. The synopsis S32::Temporal has been heavily revised in the past year, and today’s post details some of the basics of time as it is implemented in Perl 6.

time and now

The two terms that give the current time (at least what your system thinks is the current time) are time; and now. Here’s a quick example:
> say time; say now;
1292460064
Instant:2010-12-16T00:41:4.873248Z

The first (obvious) difference is that time returns POSIX time, as an integer. now returns an object known as an Instant. Use now if  you want fractions of a second and recognition of leap seconds. time won’t give you fractions of a second or leap seconds, because it returns POSIX time. Which one you use all depends on what you need.

DateTime and friend

Most of the time, you will want to store dates other than now. For this, the DateTime object is what you need. If you want to store the current time, you can use:

my $moment = DateTime.new(now); # or DateTime.new(time)

Otherwise, there are two ways of creating a DateTime object:

my $dw = DateTime.new(:year(1963), :month(11), :day(23), :hour(17), :minute(15));

This is in UTC, if you want to enter it in in another timezone, use the :timezone adverb. Here, only :year is required, the rest defaults to midnight on January 1 of the year.

This way is also pretty tedious. You could instead create a DateTime object by inputting an ISO 8601 timestamp, as a string.

my $dw = DateTime.new("1963-11-23T17:15:00Z");

The Z denotes UTC. To change that, replace Z with +hhmm or -hhmm, where ‘hh’ is the number of hours offset and ‘mm’ the number of minutes.

There is also a Date object, which is created in a similar way, but without hours, minutes, or seconds. For example:

my $jfk = Date.new("1963-11-22"); # you can also use :year and so on

The introduction of the Date object is actually a lesson from CPAN’s DateTime module: sometimes you want to treat days without having to worry about things like time zones and leap seconds. It’s inherently easier to handle pure dates. For example Date has built-in .succ and .pred methods, so you can increment and decrement them in your code.

$jfk++; # Day after JFK

Finally…

That’s about it for Time in P6. To see all the gritty details go to the Temporal specification or ask about it in the community!


Follow

Get every new post delivered to your Inbox.

Join 36 other followers