Day 4 – Quantum Secret Santa

Much has already been written about the relationship between Santa Claus and quantum mechanics.  This makes sense intuitively — Unobservable?  In multiple places at once? We only see the effects? It almost goes without saying that Santa is a macroscopic quantum phenomenon.

Similarly,  the game of secret santa has been analyzed by combinatorists and cryptographers for quite some time.  How many ways can people give gifts to each other? How can Alice and Bob and their friends have a decent protocol for their secret santa party?

But the application of quantum states as a practical solution to secret santa didn’t become evident to me until this holiday season. The situation was this: my family and I are hosting guests from out of town. We need to organize a secret santa gift exchange, but don’t want to impose gift giving or secrecy constraints on people who are coming from the same household. More explicitly:

  1. Several households of people are coming to visit us.
  2. Everyone needs to be assigned to give a gift to someone else.
  3. Everyone needs to be given their assignments ahead of time.
  4. Nobody should be assigned to someone within their household.

Sounds like a job for Perl 6!

Before getting to the solution, let’s go through some background and prerequisites for solving this.

First, quantum superpositions.

Way back in 2000, Damian Conway wrote Quantum::Superpositions for Perl 5. The cool idea here was that instead of dealing with qubits, we could deal with a macroscopic version — variables that have several values at the same time. This idea was then brought into Perl 6 in the form of junctions — logical superpositions of values  — a variable representing several values at once.  Such variables can be treated like a single value, but operators and methods apply to all the values (and can be autothreaded). The routines any, all, one and none turn a list of values into a junction.  Without even reading the documentation or thinking about quantum theory, though, these examples make sense if you just say them out loud:

say so (1, 2, 3).all < 4;  # True
say so (1, 2, 3).any < 3;  # True
say so (1, 2, 3).one < 2;  # True
say so (1, 2, 3).none > 10; # True

As in, “So,  1, 2 and 3 — all of them are less than 4?”

Multiple junctions can be part of an expression, for instance:

say so (1, 2, 3).all < (7, 8, 9).all;    # True
say so (1, 2, 3).all == (4, 5, 6).none;  # True

Think: all of 1, 2, and 3 are less than all of 7, 8, and 9?

By the way, so casts an expression to boolean.

The second prerequisite to solving our secret santa problem is set operations. Unicode characters that serve as set operators are really convenient here.

Basically, the Unicode set operators all work just as you would expect.  Quick — what do think is the output of these statements?

say so (2, 4) ⊂ (2, 4, 6);
say so 2 ∈ (1, 2);
say so 10..20 ⊆ 10..20;

Really, the only tricky thing here is how do you type ⊆, ∈, ⊂ and others on your keyboard?  (Answer: command-control-space on a mac,  control-K + “(” + “_” in vim. Actually, there’s a section of the perl6 documentation about this very topic.). These operators are defined on sets.  But also, using one of these operators on a List will automatically create a set.

The third thing to know about is the Z meta operator — this zips two things together.  The way in which the corresponding elements are combined is determined by a parameter — another operator (which is why it’s a meta operator).

say (1, 2, 3) Z+ (4, 5, 6)  # (5, 7, 9)
say (1, 2, 3) Z=> (4, 5, 6) # (1 => 4 2 => 5 3 => 6)

If Z is given =>, the pair constructor, it’ll make a list of pairs (which can be cast into a hash).

Okay — enough prerequisites.  Let’s write the program already!

my $groups = ( <comet cupid rudolph>, <dancer prancer>, <donner blitzen> );
my @santas = $groups.flat;
my %pairs;

repeat {
 %pairs = @santas Z=> @santas.permutations.pick;
} until %pairs.none.kv ⊆ $groups.any;

Oh, I almost forgot: permutations gives you a list of all permutations of a list.  Also pick returns a random element of a list.

Anyway, the hard part is done!  That clause in the until section works like this: %pairs.none returns a junction of pairs.  Calling kv on that junction makes a junction composed of two-element lists (keys and values of the pairs).  Meanwhile, $groups.any makes a junction of the list of lists. The subset operator, ⊆, then asserts that none of the elements of the left hand side are subsets of any of the elements of the right hand side.  i.e. none of the key-value pairs are subsets of any of the groups. Once again, writing it out in English is pretty similar to how it looks in Perl 6.

To notify everyone, we are going to send an email.  We put everyone’s email addresses into a hash:

my %emails =
   comet   => 'comet213@our.home',
   cupid   => 'cupid99@our.home',
   rudolph => 'rudolph101@our.home',
   dancer  => 'dancer99@reindeer.game',
   prancer => 'prancer1@reindeer.game',
   donner  => 'donner99@reindeer.party',
   blitzen => 'blitzen2@reindeer.party';

Then we can use run to use an external program — sendmail (or postfix, msmtp, or any similar mailer) — to send out the message.

for @santas.sort -> $santa {
    my $p = run '/usr/sbin/sendmail', %emails{$santa}, :in;
    $p.in.say: qq:to/END/;
       From: santa@north.pole
       To: { $santa.tc } <{ %emails{$santa} }>
       Subject: 🎅

       Dear { $santa.tc },

       Please get a gift for { %pairs{$santa}.tc }!
       END
 $p.in.close;
}

Notice that we use .tc to capitalize the name.  This stands for “title case” — a Unicode generalization of upper casing the first letter. For instance, a name like ʣenana (in which the first character is a single Unicode character — a digraph) would be properly title cased as Dzenana, not DZenana.

That’s it for the program — after showing everyone the complete program on github, even the least technical guest was quickly able to understand how it worked.  It ran smoothly and now everyone’s ready for the holidays!

 

Day 3 – Object Hashes

A short .promotional message: You may want to check out my Kickstarter campaign for Learning Perl 6, or the stuff I’m writing at the book’s website.

Perl 6 adds object hashes in which the keys aren’t merely strings. They are values and types put together. That means that the objects can stringify to the same thing but they can be different keys.

First, consider this normal hash construction. I’ll put a bunch of things into the hash then see what I got:

use v6;

my Int    $int     = 4;
my Str    $str     = "4";
my IntStr $int_str = <4>;  # Allomorph

my %hash;
%hash{$int}     = 'Plain old number';
%hash{$str}     = 'String of digits';
%hash{$int_str} = 'Dualvar';

say "There are ", %hash.elems, " elements in the hash";

# this calls the .gist method, sorta like a dumper routine
%hash.say;

The output shows that I only have one element in the hash and it’s the last one that I added:

There are 1 elements in the hash
{4 => Dualvar}

But, I can declare my hash in another way. I can declare it as an object hash by telling it what sort of objects I want it to accept. I can use the Any object which allows it to accept, well, anything:

my %hash{Any}; # accept any sort of object

This program is almost exactly the same but it acts much differently:

use v6;

my Int    $int     = 4;
my Str    $str     = "4";
my IntStr $int_str = <4>;  # Allomorph

my %hash{Any};
%hash{$int}     = 'Plain old number';
%hash{$str}     = 'String of digits';
%hash{$int_str} = 'Dualvar';

say "There are ", %hash.elems, " elements in the hash";

# this calls the .gist method, sorta like a dumper routine
%hash.say;

Now I see that I have three elements in the hash. It looks a bit strange in the .gist form because it appears that it has three keys that are all 4:

There are 3 elements in the hash
{4 => Dualvar, 4 => Plain old number, 4 => String of digits}

I can look at the .perl method that looks a bit more behind the scenes:

%hash.perl.say;

Now I see that there are three different sorts of objects:

There are 3 elements in the hash
(my Any %{Any} = IntStr.new(4, "4") => "Dualvar", 4 => "Plain old number", "4" => "String of dig<4>")

With an object hash, testing for existence is a bit different. It uses the .WHICH method, comparing the keys with the object identity operator ===.

So, I’ll put the same stuff in the hash then make a different object that I assign to $other_int. I check to see if $other_int is in the hash:

use v6;

my Int    $int     = 4;
my IntStr $int_str = <4>;  # Allomorph

my %hash{Any};
%hash{$int}     = 'Plain old number';
%hash{$int_str} = 'Dualvar';

my $other_int = 4;

# what are these things?
say "int: " ~ $int.WHICH;
say "other: " ~ $other_int.WHICH;

# are they the same?
say $int === $other_int ?? 'Same object' !! 'Different object';

# is it in the hash?
say %hash{$other_int}:exists ?? 'Other int exists in hash' !! 'Other int not there';

say %hash{"4"}:exists ?? '"4" exists in hash' !! '"4" not there';
there';

I can see that $int and $other_int look like the same object. However, the key "4" is not there even though it’s the same string as 4:

int: Int|4
other: Int|4
Same object
Other int exists in hash
"4" not there

That can be a bit weird if I wasn’t expecting that.

Consider the angle brackets version of quote words operator, <...>. This form of quote words creates allomorphs. When it sees things that look like numbers, it creates an object such as IntStr that inherits from both number and string sides. This means, though, that as an object hash key it has a very particular form. In this object hash, I make one element with the <...> quoting around the key 4. Then, I test to see if the string "4" is in the hash:

use v6;

my %hash{Any};

%hash = <4 hello>;

say %hash{"4"}:exists ?? 'Exists in hash' !! 'Not there';

And, I see that it’s not in the hash:

Not there

The allomorph version is an IntStr, but the "4" is a Str. They are not the same object, so the latter one is not a key in the hash.

That’s not a big deal if you are expecting that. But, consider a more useful object hash that only allows a certain sort of object. Maybe I want them to all be Date objects. This way, I force people to go through a central way of making keys. If they try to go around that, things don’t work:

my %hash{Date};

%hash{ Date.new(now) } = ( event => 'Something cool', rating => '6 stars' );

my $too_cool_for_your_api = '12-03-2016';

say %hash{ $too_cool_for_your_api };

I get an exception when I try to go around the constraint when I think I know better than the API:

Type check failed in binding to key; expected Date but got Str ("12-03-2016")

Perl 6 lets me force the other programmers to construct the hash keys just the way I need them.

Day 2 – Bioinformatics with Perl 6

Summer of 2016 and I’m preparing to help teach a class on metagenomics with my boss, Dr. Bonnie Hurwitz, at The University of Arizona.  She and I are both alumi of Dr. Lincoln Stein’s lab when he was at Cold Spring Harbor where we worked on Gramene, a comparative genomics platform for plants.  Way back in 1999, Lincoln created an intensive two-week course at CSHL called “Programming for Biologists” to teach everything from Unix to Perl to BLAST and CGI.  I was fortunate to be a teaching assistant several times over the years and came to enjoy helping bench scientists learn computational tools and techniques.  In the fall 2015 debut class of Bonnie’s class, we used Lincoln’s material to teach Perl 5, but I was ready to push into a new language.

Over the years, I’ve played with Python, Lisp, Ruby, Haskell, Prolog, and others.  Python would have been the obvious choice to teach our students, but I felt like I already knew an interpreted, dynamically typed language.  While I admire the type safety of Haskell, I can’t imagine being able to teach command-line Unix, HPC, metagenomic analysis, and Haskell to absolute beginners in one semester.  I decided to spend a month over the summer writing in Perl 6, and it didn’t take long until I was hooked.

There were no print books available and only a handful of online resources like https://docs.perl6.org/http://perl6intro.com/, and https://learnxinyminutes.com/docs/perl6/.  None of these were tailored to beginning scientists, so I started writing my own.  My idea was to teach solutions to common problems in biology using the various styles and strengths of the language.  For each task, I present maybe 2 or sometimes 6 versions, usually getting shorter as I teach more powerful techniques gained by functional programming techniques or object-oriented programming.

As an example, our students are writing their final program for the semester, wrapping up a re-analysis of the skin microbiome (Grice et al 2011).  Over these last few months, they’ve followed a series of detailed protocols to download the raw reads, push them through quality control measures, assemble into “contigs” (contiguous bits of sequence), call putative genes, estimate taxonomy, and annotate gene to determine the functions of the organisms at the various body sites (e.g., armpit vs toe web).  Their last assignment is to annotate the contigs with KEGG categories.

Since KEGG supports itself with yearly subscriptions, among other funding, they don’t make it exactly easy to get all the data our students need.  We used uproc to attach KEGG identifiers, and we want to group those identifiers into categories to find the top 5 functions happening in each student’s subset of samples. I found a handy shell script to use the KEGG API to download KEGG-IDs-to-pathways and pathways-to-categories.  So now we need to link KEGG IDs (e.g., “K01425”) to the pathway category (e.g., “GABAergic synapse”) via the “path:map04727”:

$ head -1 path:map04727.ko
path:map04727 ko:K01425
$ grep map04727 pathway.list
path:map04727 GABAergic synapse

Here’s a script that accomplishes the task:

#!/usr/bin/env perl6

sub MAIN (
    Str  :$pathway-list where *.IO.f = 'pathway.list',
    Str  :$pathway-dir  where *.IO.d = 'pathways',
    Str  :$out-file = 'kegg-cats.txt',
    Bool :$force    = False,
) {
    if $out-file.IO.f && $force == False {
        my $overwrite = prompt "'$out-file' exists. Overwrite [yN]? ";
        exit unless $overwrite.lc.starts-with('y');
    }

    my $out-fh = open $out-file, :w;
    my %map    = $pathway-list.IO.lines.map(*.split("\t")).flat;

    for dir($pathway-dir).grep(/'.ko'$/).kv -> $i, $ko {
        printf "%3d: %s\n", $i + 1, $ko.basename;

        for $ko.IO.lines.map(*.split("\t")) -> ($map-id, $ko-id) {
            my $cat     = %map{ $map-id } or next;
            my $kegg-id = $ko-id.subst(/^'ko:'/, '');

            if $kegg-id.match(/^ K \d ** 5 $/) {
                $out-fh.put(join "\t", $kegg-id, $cat);
            }
        }
    }

    put "Done, see '$out-file'.";
}

I’d like to break this down to explain all the lovely goodies.  First and thing-that-completely-sold-me-on-Perl-6 is the special MAIN subroutine and all the goodness packed into signatures.  Named arguments, e.g., “–pathway-list,” can defined by creating Pairs, which is as simple as putting a “:” in front of the variable that will hold the argument’s value.  I can assign a default value with “=”, constrain the value with a Type like “Str” or “Bool,” and even add arbitrary conditions like checking if the argument is an existing file (“*.IO.f”) or directory (“*.IO.d”).  If I see myself reusing those same checks (e.g., I take multiple “file/dir” arguments), I can easily create my own “subset”:

subset File of Str where *.IO.f;
sub MAIN (File :$file1, File :$file2) { ... }

I like to use reasonable defaults for my arguments, and here I wanted to show how I could check if the output file already exists and how to ask the user via “prompt” if they wish to overwrite it.  In Perl 5, I would have written:

exit unless lc($overwrite) =~ /^y/;

A direct translation to Perl 6 would use “.lc” (lowercase) as a Str method and using the ~~ “smart match” operator:

exit unless $overwrite.lc ~~ /^y/;

But here I wanted to show a more Python-ish use of “starts-with” so as to avoid freaking out beginners with regular expressions.  (I like that Perl has a long history of borrowing/stealing the best features of other languages!)

I am very happy with the new “open” routine as the Perl 5 way always seems backwards:

open my $fh, '<', $file; # Perl 5 open $file for read
my $fh = open $file;     # Perl 6 open $file for read

Here, I need to open the output file for writing, so I pass the “:w” (writable) flag which is just a short-hand for the Pair w => True.

The next line is an extremely condensed way to read a tab-delimited file of two columns directly into a hash.  Here is what my “pathway.list” file looks like:

$ head -3 pathway.list
path:map00010 Glycolysis / Gluconeogenesis
path:map00020 Citrate cycle (TCA cycle)
path:map00030 Pentose phosphate pathway

From that, I want a list of the “path:map” string to the category on the right.  So, let’s use the REPL (the second thing that totally sold me on Perl 6) to see how this is built:

$ head -3 pathway.list > test
$ perl6
To exit type 'exit' or '^D'
> 'test'.IO.lines
(path:map00010 Glycolysis / Gluconeogenesis path:map00020 Citrate cycle (TCA cycle) path:map00030 Pentose phosphate pathway)
> 'test'.IO.lines.map(*.split("\t").join('=')).join(', ')
path:map00010=Glycolysis / Gluconeogenesis, path:map00020=Citrate cycle (TCA cycle), path:map00030=Pentose phosphate pathway

File I/O is very easy (IMHO) — I can coerce/cast a variable with “.IO” and then call “lines” (or “words” or even “comb” if I wanted letters).  Here I want to process each line, using our trusty old “map” (from functional programming) to apply the “split” function to the “*” (Whatever) to get a list which, for visual purposes, I join on “=”.  The result of the lines/map is itself a list which I joined on commas so you can see the two lists together.

Something that is completely different between Perl 5 and 6 is how they handle lists of lists.  Perl 5 would flatten them:

  DB x ((1,2), (3,4))
0 1
1 2
2 3
3 4
 DB x scalar ((1,2), (3,4))
0 4

But Perl 6 allows nesting:

> ((1,2), (3,4))
((1 2) (3 4))
> ((1,2), (3,4)).elems
2

But I can’t create a hash from a list of lists, only from a list of pairs:

> my %h = ((1,2), (3,4))
{1 2 => (3 4)}
> my %h = 1 => 2, 3 => 4
{1 => 2, 3 => 4}

I need to flatten my list-of-lists:

> my %h = ((1,2), (3,4)).flat
{1 => 2, 3 => 4}

And that is how I get my hash-from-a-tab-file:

> my %h = 'test'.IO.lines.map(*.split("\t")).flat
{path:map00010 => Glycolysis / Gluconeogenesis, path:map00020 => Citrate cycle (TCA cycle), path:map00030 => Pentose phosphate pathway}

There are a few things I’d like to explain in this line:

for dir($pathway-dir).grep(/'.ko'$/).kv -> $i, $ko

The “dir” routine gives you a directory listing, and, since my type constraint already checked that the variable is an existing directory, I can rest assured that this will work.  The result of “dir” is a list of IO::Path objects, and I can “grep” (“filter” in some other languages) for those that smart-match to the pattern of the string “.ko” anchored to the end (“$”).  (I could have also used the Python-like “ends-with” method.)

The result of the dir/grep call is a list, and as I wrote in another post, you can call call “kv” (as well as “pairs“) on any list to get both the position and value of each member:

> ("foo", "bar").kv
(0 foo 1 bar)
> ("foo", "bar").pairs
(0 => foo 1 => bar)

The other bit of awesomeness is that Perl 6 allows you to consume a variable number of elements of  a list with optional defaults if the list is not evenly divisible by the number of elements you’ve requested:

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

Heck, you don’t even have to declare them as we have implicit variables:

> for 1..4 { put "$^a, $^b" }
1, 2
3, 4

So then I have a (zero-offset which is why I add 1) file number and name which I can use to print my progress using “printf.”  In Perl 5, I would have to establish my counter $i before the loop (which means it would continue to be visible after the loop) and be sure to increment the counter while understanding the nuances of ++$i vs $i++:

# Perl 5
my $i = 0;
for my $word (qw[foo bar]) {
    printf "%3d: %s\n", ++$i, $word;
}

While trying similar things in Haskell, I learned to zip (Z) an infinite list of integers (Haskell, like Perl 6, is lazy!) with my list of interest like so:

> for 1..* Z "foo", "bar" -> ($i, $word) { put "$i = $word" }
1 = foo
2 = bar

OK, that was a long tangent, so let’s return to the program.  We left off with this statement to find all the pathway/KEGG ID files:

for dir($pathway-dir).grep(/'.ko'$/).kv -> $i, $ko

As before, I use “.IO.lines” to read each mapping file, also running each line through a similar “split” on tabs to break the lines into the mapping ID and KO ID:

for $ko.IO.lines.map(*.split("\t")) -> ($map-id, $ko-id)

The long-hand way to do this would be:

for $ko.IO.lines -> $line {
    my ($map-id, $ko-id) = $line.split("\t");
}

As in Perl 5, “next” and “last” are still part of control flow, and I skip over mapping IDs that I didn’t find in the mapping file:

my $cat = %map{ $map-id } or next;

The KO ID looks like “ko:K00001”, so I need to remove the leading “ko:” which is easily accomplished with the “subst” (substitute) operation:

my $kegg-id = $ko-id.subst(/^'ko:'/, '');

In Perl 5 I would have done this, which I feel is unquestionably more opaque:

(my $kegg_id = $ko_id) =~ s/^ko://;

It’s worth noting that in Perl 5 I might also have made the decision to reuse and mutate the $ko_id like so:

$ko_id =~ s/^ko://;

But in Perl 6, the my $ko-id variable is not actually variable — by default it is read-only.  In the following example, you see that “subst” returns a new string with the substitutions requested, but the string itself remains unchanged:

> for "foo", "bar" -> $s { put $s.subst(/<[aeiou]>/, 'X', :g); put $s }
fXX
foo
bXr
bar

If I try to call the mutator method, I get an error:

> for "foo", "bar" -> $s { $s.subst-mutate(/<[aeiou]>/, 'X', :g); put $s }
Cannot resolve caller subst-mutate(Str: Regex, Str, :g); the following candidates
match the type but require mutable arguments:
 (Cool:D $self is rw: |c is raw)
 (Str:D $self is rw: $matcher, $replacement, :ii(:$samecase), :ss(:$samespace), :mm(:$samemark), *%options)
 in block  at  line 1

I have to explicitly say the variable is a copy:

> for "foo", "bar" -> $s is copy { $s.subst-mutate(/<[aeiou]>/, 'X', :g); put $s }
fXX
bXr

All this is a nod to the very good influence of purely functional programming languages where data is immutable.  It’s not nice to always be constrained by this idea, but here the application, I believe, enforces a very good programming practice.

Some of the KEGG IDs might be “KO” (KEGG Orthology), so I want to ensure that I’m only dealing with strings that look like “K00001” — a capital “K” followed by five digits:

if $kegg-id.match(/^ K \d ** 5 $/) {

It’s also possible to write that with the smart-match operator.  Both will return Match if successful:

> 'K00001' ~~ /^ K \d ** 5 $/
「K00001」
> say ('K00001' ~~ /^ K \d ** 5 $/).WHAT
(Match)
> my $m = 'K00001' ~~ /^ K \d ** 5 $/
「K00001」
> dd $m
Match $m = Match.new(ast => Any, list => (), hash => Map.new(()), orig => "K00001", to => 6, from => 0)

The ecosystem of native Perl 6modules currently includes BioInfo and BioPerl6.  What’s amazing, though, is that you can use Inline::Perl5 to bring in Perl 5’s BioPerl:

$ cat seqs.fa
>GON5MYK01BC2ZU
CTGTCTGTAACCTCTGCCAGCATGCAGGCGCGTGCTGCGTACCTGAACGAAGGTTGGAAC
TGCATGAACTTGGTGAAGAACATCACCAAGCAAGACCCGCTAGAGTTTGTCGCTAACCGC
CTCACTAGCTATTGGCAGCGCGTAGCCCAGCGTCGCGCTATTCGCCACCACTATCGGCAT
CTACAACGAAAATGTT
>GON5MYK01AXF84
CTTGAGCAAGACCTGCGCCGACTTGTCCTGTTTTCAACTAACTTAGCACCTACGTTACGA
ATAAATCTATCAAATTGTGGTGTGCCAAAAATATCTGATATGCTTGGTCTTTCTGTTTGT
TCTGTAACTTTATCTGTAGGTTTTTC
>GON5MYK01DJ0V1
CATTACTGAAATCTGTCCAGTATTCCACATACAAGAAAGGTCTTGTATCGGAGCTGTTGT
CTACACCTTTAATAGTAAAGTGACGTGTCAATATCTGAACCAGTGATCCAACCTTGTGCT
TATGTCTGACTTCATCATCAAGTGTTAGTGTCGTG
>GON5MYK01DR4LG
AGAAGTAAAAATCAGCAGAGACTTCGACATCGAAAGATTAATTGGTCAAGATATTACAGC
TTTAACATCTCTATTCGATCAACAAGTCATTAGATAGAGACGAATTTAGAGATATTTTAG
TTCAAGGTG
$ cat inline.p6
#!/usr/bin/env perl6

# This is using p5 BioPerl Bio::SeqIO
use Bio::SeqIO:from<Perl5>;

my $file = @*ARGS.shift;

# Note: left side needs quotes; keys are not automaically strings in p6
my $in = Bio::SeqIO.new('-format' => 'fasta', '-file' => $file);

my $ct = 0;
while $in.next_seq -> $record {
    $ct++;
    say $record.display_id;
}

say "Count: $ct";
$ ./inline.p6 seqs.fa
GON5MYK01BC2ZU
GON5MYK01AXF84
GON5MYK01DJ0V1
GON5MYK01DR4LG
Count: 4

Like Perl 5, version 6 still (IMO) makes easy things easy and hard things possible, and I hope this article makes you want to use Perl 6 today.  I will continue to add chapters and examples to my book and Github repo in the hopes that people will steal as much as they need to get started.

Happy Hacking to one and all!

Day 1 – Consuming GitHub Webhooks

Welcome Back

Welcome to the first Advent post of 2016; this marks almost the first anniversary of the release of the Perl 6 specification. Rakudo Perl 6 has released a compiler for over 100 months (even before the release of the actual specification). The releases this year each come with bug fixes, speed improvements, and occasionally new features that will probably become part of the next version of the specification.

For the first advent article this year, I wanted to share an experience where I was able to use Perl 6 for one of the strengths that it inherited from its older sibling: whipuptitude (coined by Larry – “the aptitude for whipping things up”). When I was given the task of getting something working quickly at $DAYJOB recently, it was the tool I reached for.

Consuming Github Webhooks

The task was to setup a tool that would, for a variety of projects in github enterprise, create a docker image every time someone pushed a commit to the mainline development branch.

Start Listening

If you have a github project, you may have seen in the settings that you can setup a webhook – an HTTP call that is triggered after certain events occur in the repository. Let’s create a test repository in github (or github enterprise if you have access to one at work); For the public github, you can go to https://github.com/new, pick a new repository name, select “Initialize this repository with a README”, and click “Create Repository”

Now let’s turn on a webhook. (For this to work, you’ll need to be able to make an http connection from the github/enterprise to your local machine.) Go to the repository’s settings, pick Webhooks, then “Add webhook”. Note that the webhook says that it will be a POST request, and can send JSON: we’ll need that later.

Pick a port, e.g. 7890, so the payload URL will be something like: http://somemachine.your.co:7890/build

For this proof of concept, we just need git push events (the default). Click “Add webhook” to finalize this hook. Now commit something to your test repository. You can see the error the webhook reports – it couldn’t connect. So, our first step is to be able to pick up when the webhook calls.

Looking through the Perl 6 ecosystem (http://modules.perl6.org/), we find Bailador, a Perl 6 play on 5’s Dancer, that will let us run a local HTTP server. After installing that module with zef or panda, we can write a barebones program that will let us listen to all POST requests on a particular port. We use the .* regex to indicate all paths, and give it an anonymous sub as a callback. The callback outputs a line when called, then tells github that everything is “OK”. The last line tells Bailador to listen on that port.

use Bailador;
post /.*/ => sub {
    say "Hello?";
    "OK";
}
baile(7890);

Now if we run this script, it blocks, waiting for connections. Push another commit to your git repo, and now you can see that everytime you push, our script wakes up, Bailador notes that it received a POST to the “/build” URL, and our callback emits “Hello?”, and then waits again.

What did you say?

Our next step is to see what data github is actually sending us: easy enough, let’s dump out the HTTP request that was shipped, using a sigilless variable that is made available to us in a Bailador routing callback. Let’s also replace our previous regex with the path “/build” to match the URL we gave the webhook.

use Bailador;
post '/build' => sub {
    say request.body;
    "OK";
}
baile(7890);

After another push, we can verify that github is sending us a body consisting of JSON, just like it said it would. Digging into the ecosystem again, we pick one of the JSON modules, and use that to convert the JSON string we get into an actual Perl 6 data structure:

use Bailador;
use JSON::Fast;
post '/build' => sub {
    say (from-json request.body).keys;
    "OK";
}
baile(7890);

Pushing now gives us a list of the top level keys of the JSON structure. The JSON from the request body is converted to a hash with the module’s from-json routine, and then we print just the keys from that structure. Now we can actually start processing some data.

What do I want?

We’re going to need to know what repository we’re working with, where to checkout a copy, and which branch it was on. We’ll ignore the revision and just assume we need to grab the latest version each time we get a push. Looking at the output from the previous dumps above, we can pull out the specific information we need from the data.

use Bailador;
use JSON::Fast;
post '/build' => 
    my $data = from-json request.body;

    my $repo      = $data<repository><full_name>;
    my $clone-url = $data<repository><ssh_url>;
    my $branch    = $data<ref>.split('/')[*-1];

    dd $repo, $clone-url, $branch; 
    "OK";
}
baile(7890);

The $data<key> syntax lets us index into $data with a literal key. For the branch, we split up the refs/heads/master into chunks by / and then pick the last entry. Note that we use Rakudo’s un-specced helper routine dd to pretty print the three variables to make sure we’re pulling the right data.

Now we have enough data to pull a copy of the repo and do some work! If the branch in question is the right one, we’re going to want to get a checkout and do a build on the HEAD of that branch. While for $DAYJOB, we did a docker build and pushed that up to a registry, for this sample, we’ll just checkout a copy.

    use Bailador;
    use JSON::Fast;
    post '/build' => sub {
        my $data = from-json request.body;

        my $repo      = $data<repository><full_name>;
        my $clone-url = $data<repository><ssh_url>;
        my $branch    = $data<ref>.split('/')[*-1];

        return "OK" if $branch ne "master";

        qqx/rm -rf "$repo"/;
        qqx/git clone --branch $branch --depth 1 "$clone-url" "$repo"/;


        "OK";
    }
    baile(7890);

The callback now bails out early if the branch we were called on isn’t master. We shell out to remove the repo directory (as coke on github, my tests in writing this article were on coke/demo), and then do minimal git clone of the appropriate branch. Since we’re shelling out, you can easily add your actual build/upload step here as well.

Too Slow?

Once we added the checkout step, you may have noticed that github complains of a timeout. Because we don’t care to report back to github if a particular revision successfully built or not (we’re just creating a build), there’s no need to wait for it to complete. Perl 6 makes this very easy. Our final version has just one more word and a block:

use Bailador;
use JSON::Fast;
post '/build' => sub {
    my $data = from-json request.body;

    my $repo      = $data<repository><full_name>;
    my $clone-url = $data<repository><ssh_url>;
    my $branch    = $data<ref>.split('/')[*-1];

    return "OK" if $branch ne "master";

    start {
        qqx/rm -rf "$repo"/;
        qqx/git clone --branch $branch --depth 1 "$clone-url" "$repo"/;
    }

    "OK";
}
baile(7890);

The start block here begins an asynchronous request. The POST callback skips over this and immediately returns “OK” to the github webhook, while Perl 6 queues our clone (and eventually our build) to run in the background.

What Next?

We were able to implement this solution without knowing much about webhooks up front (just that they are HTTP POST requests), iterating our Perl 6 script as we were able to see more information at each step.

Granted, this was the bare minimum to get things working for a project at my $DAYJOB – you might have more requirements, or have more time to play. Some experiments you could do to extend this script:

  • Add HTTPS support
  • Change the git checkout to keep a cached version that uses ‘clone –mirror’, and then fetches instead of cloning each time.
  • Create a local YAML config file that allows you to change the branch that triggers the build for each repository. (Or a DB connection, or…)
  • Make the handler smart enough to process each commit rather than just the latest commit when we are called.
  • Customize the script to actually do a build for your project.

Cheers!

Christmas announcement, two.

As we prepare to cut the first monthly release of the Rakudo Perl 6 compiler of 2016, we wanted to specifically thank all the individuals, companies, and organizations who donated money, services, equipment, or their employee’s time to the effort.  This includes efforts going back to 2000 over multiple Perl 6 related projects. As with our developer list on the Christmas release, our sincere apologies to anyone who was accidentally left off this list.

  • ActiveState
  • BBC
  • Blackstar
  • Booking.com
  • craigslist
  • Richard Dice of Toronto.pm
  • Dijkmat
  • Edument
  • ETH Zürich
  • Google Summer of Code
  • Ian Hague
  • Manning Publications
  • Morgan Stanley
  • Mozilla
  • NLNet
  • noris network AG
  • O’Reilly Media
  • Frédéric Schütz of the Swiss Institute of Bioinformatics
  • Stonehenge Consulting
  • The Perl Foundation
  • TPF’s Perl 6 Core Development Fund sponsors
  • VA Linux
  • WenZPerl
  • Fritz Zaucker of Oetiker+Partner AG

Again, thank you all for your support.

Christmas is here.

On behalf of the Rakudo development team, I’m proud to announce the Christmas release (December 2015) of Rakudo Perl 6 #94 “коледа”. Rakudo is an implementation of Perl 6 on the Moar Virtual Machine[^1].

This is the Christmas release of Rakudo Perl 6. This version of the compiler targets the v6.c “Christmas” specification of the Perl 6 language. The Perl 6 community has been working toward this release over the last 15 years. Together, we’ve built a language that:

  • Retains the core values of Perl: expressiveness, getting the job done, taking influences from natural language, and pushing the boundaries of language design
  • Has clean, modern syntax, rooted in familiar constructs but revisiting and revising the things that needed it
  • Is truly multi-paradigm, enabling elegant object-oriented, functional, procedural, and concurrent programming
  • Serves as a great glue language, allowing for easy calling of C/C++ (using NativeCall) and staying compatible with Perl 5 (via Inline::Perl5).
  • Provides composable constructs for working with asynchronous data and parallel computations
  • Dramatically reforms and sets a new standard in regex syntax, which scales up to full grammars – powerful enough to parse Perl 6 itself
  • Has outstanding Unicode support, with strings working at grapheme level
  • Values lexical scoping and encapsulation, enabling easy refactoring
  • Is extensible through meta-object programming, user-defined operators, and traits

The tag for this release is “коледа”[^2], a slavic word for an ancient winter festival that has been incorporated into Christmas. We hope you join us in our celebration of getting our Christmas release shipped!

While we are extremely happy to ship an official Perl 6 release, this is not the end of Rakudo’s development. We will continue to ship monthly releases, which will continue to improve performance and our users experience. We’ll also continue our work on the specification, with feedback from the community.

To be clear on that point, this Rakudo release is not considered the primary deliverable for this Christmas; it is the language specification, known as “roast” (Repository Of All Spec Tests), that is considered the primary deliverable. The specification tests that define this 6.c version[^3] of the language are now frozen, and we hope it will be quite some time before we feel obligated to define a 6.d (Diwali) version of the language.

This Rakudo release targets those tests (over 120 thousand of them), and passes them all on at least some architectures when the moon is in the right phase. But Rakudo itself is not frozen. There is still plenty of work ahead for us to improve speed, portability, and stability. Do not expect the level of perfection that you see in established products. This is essentially a .0 release of a compiler. We do not claim an absence of bugs or instabilities. We do not claim the documentation is complete. We do not claim portability to many architectures. We do not claim that all downstream software will work correctly. Think of it as a first kernel release, and now we get to build and port various distributions based around that kernel.

What we do claim is that you now have a stable language specification, and you can enjoy getting some stuff done with Perl 6 without us breaking it every month—as long as you stick to the features that are actually tested in the test suite, that is. Please note that any “feature” you discover that is not tested in the test suite is considered fair game for change without notice.

Have the appropriate amount of fun!

The tarball for this release is available from http://rakudo.org/downloads/rakudo/.

Please note: This announcement is not for the Rakudo Star distribution[^4] — it’s announcing a new release of the compiler and the specification. For the latest Rakudo Star release, see http://rakudo.org/downloads/star/. A Christmas-based version will be available soon.

In addition to being our Christmas release, this is yet another monthly compiler release; Some of the changes that are new in release are outlined below:

New in 2015.12:

  • Fixed size and multi-dimensional typed and native arrays
  • Greatly overhauled module loading and installation, including handling precompilation at module installation time in Rakudo
  • while/until loops can now return lists of values
  • We now catch many more kinds of “Useless use of X in sink context”
  • A number of convenient Unicode equivalents were introduced
  • Superscripts can now be used for integer powers
  • Non-digit unicode characters with a numeric value (½ and such) can now be used for that numeric value
  • There is a new “approximately equal” operator
  • Add support for USAGE argument help
  • Provide tau constant (also: τ)
  • Can now use channels with supply/react/whenever
  • Bool is now a proper enum
  • Supply/Supplier improvements
  • Use of EVAL now requires a declaration of ‘use MONKEY-SEE-NO-EVAL’
  • Make pack and unpack experimental
  • Dynamic variables are now visible inside start { … } blocks
  • Autoincrements on native ints are now faster than on Int
  • The ~~ operator can now chain with other comparisons in many circumstances Various numeric operations now return overflow/underflow failures instead of wrong value
  • The :ss, :ii, and :mm options to s/// now all work together

This is only a partial list of the changes in this release. For a more
detailed list, see “docs/ChangeLog”.

The development team thanks all of our contributors and sponsors for making Rakudo Perl possible, as well as those people who worked on the design docs, the Perl 6 test suite, MoarVM and the specification. Additionally, the Pugs, Parrot, and Niecza projects were all instrumental with their contributions to the specification and the community.

The following people contributed to the development of the Christmas release. We’ve gone back through the logs of all the various projects. Thanks to everyone who has worked to make this release happen over the past 15 years. We would also like to thank everyone who submitted bug reports or dropped in on the various forums to discuss things. Finally, we’d like to extend a special thanks to everyone who we accidentally left out of this list.

Gisle Aas, abcxyzp, Chuck Adams, Colin Paul Adams, Rod Adams, C.J. Adams‑Collier, David H. Adler, Chirag Agrawal, Amir E. Aharoni, Bilal Akhtar, Julian Albo, Alekssasho, alexghacker, Paco Alguacil, Brandon S Allbery, Geir Amdal, Markus Amsler, Paul C. Anagnostopoulos, Nikolay Ananiev, anatolyv, andras, Saleem Ansari, Joji Antony, Tomoki Aonuma, Syed Uzair Aqeel, arathorn, Arcterus, Kodi Arfer, Daniel Arbelo Arrocha, ash, Ted Ashton, Arnaud Assad, atroxaper, Ori Avtalion אורי אבטליון, Auzon, Greg Bacon, Ivan Baidakou, Alex Balhatchet, Szabó, Balázs, Amir Livine Bar‑On עמיר ליבנה בר‑און, Luca Barbato, Mattia Barbon, Ann Barcomb, Christian Bartolomäus, Alex “Skud” Bayley, bcmb, Jody Belka, Shachaf Ben‑Kiki, Andrei Benea, benedikth, Zev Benjamin, benmorrow, Kevan Benson, Martin Berends, Anton Berezin, Arthur Bergman, Anders Nor Berle, bestian, Peter Bevan, Mark Biggar, Carlin Bingham, Ævar Arnfjörð Bjarmason, J. David Blackstone, Ronald Blaschke, Ingo Blechschmidt, bloonix, blwood, Kristof Bogaerts, Dan Bolser, Конрад Боровски, Christopher Bottoms, Gonéri Le Bouder, Jos Boumans, Brad Bowman, Matt Boyle, bpetering, H.Merijn Brand, Terrence Brannon, Gwern Branwen, Stig Brautaset, Herbert “lichtkind” Breunung, bri, brian_d_foy, Fernando Brito, Geoffrey Broadwell, Leon Brocard, Benjamin Brodfuehrer, Samuel Bronson, Dan Brook, Nathan C. Brown, Roger Browne, Philippe Bruhat (BooK), David Brunton, Corwin Brust, Klaus Brüssel, Lucas Buchala, buchetc, Christoph Buchetmann, Norbert Buchmuller, Buddha Buck, Alexandre Buisse, Tim Bunce, Bryan Burgers, Sean M. Burke, Matthew Byng‑Maddick, András Bártházi, Jürgen Bömmels, Caelum, Aldo Calpini, Edward Cant, David Cantrell, Carlin, Michael Cartmell, Hezekiah Carty, Nuno ‘smash’ Carvalho, Marcelo Serra Castilhos, Piers Cawley, cdavaz, cdpruden, Gianni Ceccarelli, cfourier, Marc Chantreux, Mitchell N Charity, Oliver Charles, Vasily Chekalkin, Yuan‑Chen Cheng 鄭原真, Daniel Chetlin, Hsin‑Chan Chien 簡信昌, N. Hao Ching, Joshua Choi, Elizabeth Cholet, David Christensen, chuck, cjeris, Nicholas Clark, Steve Clark, Jeff Clites, cmarcelo, cmeyer, Paul Cochrane, Daniel Colascione, Jason Cole, Will “Coke” Coleda, Sylvain Colinet, cono, Tim Conrow, Géraud Continsouzas, Damian Conway, Neil Conway, Stuart Cook, David Corbin, Deven T. Corzine, cosmicnet, Timothy Covell, Beau E. Cox, Simon Cozens, Philip Crow, cspenser, Franck Cuny, Tyler Curtis, David Czech, Daenyth, Dagur, Ritz Daniel, darkwolf, Chris Davaz, David Warring, Justin DeVuyst, Daniel Dehennin, Akim Demaille, Detonite, Lars “daxim” Dieckow 迪拉斯, Matt Diephouse, Bob Diertens, Wendy “woolfy” van Dijk, Jeffrey Dik, John M. Dlugosz, dimid, diotalevi, Hans van Dok, Chris Dolan, Mark Dominus, Bryan Donlan, Andy Dougherty, Dave Doyle, drKreso, dr_df0, dudley, Jonathan Scott Duff, dug, Lee Duhem, Darren Duncan, Andrew Egeler, Havard Eidnes, Nelson Elhage, Fitz Elliott, Alex Elsayed, Jay Emerson, Aankhola Encorporated, ennio, Enveigler, Jon Ericson, Shae Matijs Erisson, Eryq, Mike Eve, Pat Eyler, Aaron Faanes, Kevin Falcone, David Farrell, Angel Faus, Jason Felds, Paul Fenwick, Jose Rodrigo Fernandez, Nelson Ferraz, Adriano Ferreira, João Fernando Ferreira, Chris Fields, Caio Marcelo de Oliveira Filho, Steve Fink, Shlomi “rindolf” Fish שלומי פיש, Mark Leighton Fisher, Scott Fitzenrider, Dudley Flanders, Richard Foley, Vincent Foley, Julian Fondren, Ruben Fonseca, David Formosa, Karl Forner, Solomon Foster, Chaddaï Fouché, Lloyd Fournier, Michael Fowler, Matt Fowles, franck, Austin Frank, Carl Franks, Kent Fredric, Chaim Frenkel, Piotr Fusik, gabriele, John Gabriele, Christoph Gärtner, Martin von Gagern, Felix Gallo, Salvador Ortiz Garcia, Rafaël Garcia‑Suarez, Joshua Gatcomb, Jerry Gay, gcomnz, Jonathan Gentle, iVAN Georgiev, Brian Gernhardt, Bram Geron, Alessandro Ghedini, Imran Ghory, Peter Gibbs, Tanton Gibbs, Brad Gilbert (b2gills), Karl Glazebrook, Nick Glencross, Mark Glines, Flávio S. Glock, Jason Gloudon, Simon Glover, gnuvince, Garrett Goebel, Jeffrey Goff, Mikhael Goikhman, Benjamin Goldberg, Arcady Goldmints‑Orlov, Dimitry Golubovsky, Gerard Goossen, Goplat, Alex Gough, Léo Grange, Chad “Exodist” Granum, Kenneth A Graves, Bruce Gray, Nathan Gray, Mark Grimes, Lucien Grondin, Rolf Grossmann, David Grove, Marcel Grünauer, Daniel Grunblatt, Uri Guttman, gwern, Swaroop C H, Richard Hainsworth, Roger Hale, John “ab5tract” Haltiwanger, Nigel Hamilton, Eric Hanchrow, Sterling Hanenkamp, Ask Bjørn Hansen, Christian “chansen” Hansen, Eirik Berg Hanssen, Samuel Harrington, Trey Harris, John Harrison, Carsten Hartenfels, Richard Hartmann, Kyle Hasselbacher, Austin Hastings, Carl Hayter, Florian Helmberger, Gordon Henriksen, Felix Herrmann, Peter Heslin, Fred Heutte, Jarkko Hietaniemi, Michael H. Hind, Joshua Hoblitt, Zack Hobson, Eric Hodges, Rob Hoelz, Masahiro Honma, Lyle Hopkins, JD Horelick, Jeff Horwitz, Chris Hostetter, Laurens Van Houtven, Jeremy Howard, Yiyi Hu 鹄驿懿, Benedikt Huber, Brad Hughes, Sterling Hughes, Tom Hughes, Tristan Hume, Donald Hunter, Douglas Hunter, Juan Francisco Cantero Hurtado, Kay‑Uwe ‘kiwi’ Hüll, Ran Eliam, Alin Iacob, Ibotty, ibrown, ihrd, Roland Illing, Jan Ingvoldstad, Joshua Isom, isop, Ivan_A_Frey, ivanoff, Akash Manohar J, jafelds, Robert G. Jakabosky, jamesrom, S. A. Janet, jani, Heiko Jansen, Stuart Jansen, Jarrod, Jedai, Chris Jepeway, Chris Jeris, Dagur Valberg Johannsson, Erik Johansen, Paul Johnson, johnspurr, Isaac Jones, Norman Nunley, Jr, Yoshikuni Jujo, Brian S. Julin, Josh Juran, Michal Jurosz, David KOENIG, Prakash Kailasa, Shoichi Kaji, Daniel Kang, Isis Kang, Chia‑Liang Kao 高嘉良, Dmitry Karasik, Luben Karavelov, Amir Karger, Offer Kaye, Bruce Keeler, James E Keenan, Cole Keirsey, Adam Kennedy, Matt Kennedy, Shane Kerr, khairul, Mikhail Khorkov, Krzysztof Kielak, Andres Kievsky, Daehyub Kim, Rob Kinyon, Oleg Kiselyov, OOLLEY kj, Martin Kjeldsen, Thomas “domm” Klausner, Zohar “lumi” Kelrich זהר קלריך/卡卓哈, Damian Miles Knopp, Dan Kogai 小飼弾, Yuval “nothingmuch” Kogman יובל קוג’מן, Tomasz Konojacki, Vadim Konovalov, Nick Kostirya, Matt Kraai, Thomas Kratz, Adrian Kreher, John van Krieken, Matthias Krull, Bradley M. Kuhn, Bob Kuo, Colin Kuskie, Kamil Kułaga, Sage LaTorra, Brent Laabs, laben, Johannes Laire, Markus Laire, Fayland Lam 林道, Mike Lambert, lanny, Leo Lapworth, last.of.the.careless.men, Bart Lateur, Jia‑Hong Lee, Lola Lee, Jonathan Leffler, Tobias Leich, lembark, Mark Lentczner, Moritz A Lenz, Jean‑Louis Leroy, Andy Lester, Jonathan “Duke” Leto, Vladimir Lettiev, Mike Li 李曉光, Stefan Lidman, Yung‑Chung Lin 林永忠, Glenn Linderman, Vladimir Lipsky, Zach Lipton, Stevan Little, Kang‑Min Liu 劉康民, Skip Livingston, David M. Lloyd, Daniel Lo, Peter Lobsinger, Andres Löh, Nick Logan, Eric Lubow, Nolan Lum, Peter Lunicks, LylePerl, Ian Lynagh, lysdexsik, Kiran Kumar M., Jerry MacClure, Noel Maddy, Christopher J. Madsen, Abhijit A. Mahabal, Max Maischein, Peter Makholm, Ujwal Reddy Malipeddi, malon, Christopher Malon, Dagfinn Ilmari Mannsåker, Michael Maraist, Roie Marianer רועי מריאנר, markmont, Simon Marlow, martin, Paolo Martini, Ilya Martynov, Jaume Martí, James Mastros, Michael J. Mathews, Vyacheslav Matjukhin, Tokuhiro Matsuno, mattc, Mike Mattie, Elizabeth “lizmat” Mattijsen, Вячеслав Матюхин, Markus Mayr, Josh McAdams, Martin McCarthy, Mark McConnell, Steven McDougall, John McNamara, Scott McWhirter, mdinger, Olivier “dolmen” Mengué, Kevin Metcalf, Patrick R. Michaud, mimir, mjreed, Tom Moertel, Michael Mol, Paolo Molaro, Shawn M Moore, Brandon Michael Moore, Alexander Moquin, Ion Alexandru Morega, Dino Morelli, Kolia Morev, Zach Morgan, mr_ank, Alex Munroe, muraiki, Paweł Murias, mvuets, Steve Mynott, mzedeler, Carl Mäsak, naesten, Tim Nelson, Ailin Nemui, Ingy döt Net 應吉大聶, David Nicol, Faye Niemeyer, Nigelsandever, Karl Rune Nilsen, Salve J. Nilsen, Per Christian Nodtvedt, Ben Noordhuis, Paweł Nowak, Norman Nunley, Tony O’Dell, יהושע “שי” אוחיון, Clayton O’Neill, Stefan O’Rear, Sean O’Rourke, Matt Oates, Tony Olekshy, Martin Olsen, Dmitriy Olshevskiy, Dave Olszewski, Nelo Onyiah, William Orr, Jon Orwant, Andrei Osipov, Christoph Otto, Pawel Pabian, Walter Pallestrong, Luke Palmer, Bartłomiej Palmowski, Pancake, Paolo, Marton Papp, Andrew Parker, Roman M. Parparov, Anthony Parsons, Mike Pastore, Nova Patch, Timo Paulssen, Tony Payne, Stéphane “cognominal” Payrard, Slava Pechenin, Gael Pegliasco, Stéphane Peiry, Felipe Pena, Nayden Pendov, Wenzel P. P. Peppmeyer, François Perrad, Markus Peter, Ben Petering, Steve Peters, Tim Peterson, Ronny Pfannschmidt, Clinton A. Pierce, Jerrad Pierce, Thilo Planz, plunix, pmakholm, Curtis ‘Ovid’ Poe, Gerd Pokorra, Peter Polacik, Flavio Poletti, Kevin Polulak, John Porter, Ryan W. Porter, Stephen P. Potter, Philip Potter, Adam Preble, premshree, Klāvs Priedītis, Adam Prime, Richard Proctor, Christopher Pruden, Kevin Puetz, Gregor N. Purdy, purl, Hongwen Qiu, Jerome Quelin, quester, Gerhard R., Peter Rabbitson, Florian Ragwitz, raiph, Matt Rajca, Marcus Ramberg, Claudio Ramirez, Prog Rammer, Allison Randal, David Ranvig, Lars Balker Rasmussen, Curtis Rawls, raydiak, Robin Redeker, Ted Reed, Jens Rehsack, Charles Reiss, Gabriele Renzi, Kenneth C. Rich, Jason Richmond, Ryan Richter, Sebastian Riedel, Dennis Rieks, Jens Rieks, Lanny Ripple, John Rizzo, rkhill, Andrew Robbins, Amos Robinson, Jonathan Rockway, Stefano Rodighiero, Andrew Rodland, Lindolfo Rodrigues, Bob Rogers, Dave Rolsky, David Romano, ron, Eric J. Roode, Garret Rooney, Garrett Rooney, David Ross, Andreas Rottmann, Brent Royal‑Gordon, Shmarya Rubenstein, Sam Ruby, Simon Ruderich, Daniel Ruoso, Jake Russo, ruz, Joseph Ryan, Gilbert Röhrbein, Sam S, s1n, sahadev, Patrick Abi Salloum, salty_horse, Chip Salzenberg, Shrivatsan Sampathkumar, Igor Rafael Sanchez‑Puls, Hugo van der Sanden, Thomas Sandlaß, Yun SangHo, sanug, Siddhant Saraf, Sasho, Andrew Savige, John Saylor, Matt Schallert, Bernhard Schmalhofer, Arthur Axel Schmidt, Ronald Schmidt, Michael Schroeder, Steven Schubiger, Steve “thundergnat” Schulze, Andreas Schwab, Randal L. Schwartz, Pepe Schwarz, Frederik Schwarzer, Calvin Schwenzfeier, Michael G. Schwern, Steffen Schwigon, Tom Scola, Ariel Scolnicov, Michael Scott, Peter Scott, Rick Scott, Stefan Seifert, Austin Seipp, Mark Senn, Filip Sergot, Seth Gold (Sgeo), William Shallum, Kris Shannon, shenyute, Aaron Sherman, Mark Shoulson, Ryan Siemens, Ricardo Signes, Hinrik Örn Sigurðsson, Jonathan Sillito, Miroslav Silovic, Steve Simmons, Alberto Manuel Brandao Simoes, John Siracusa, Arne Skjærholt, Barrie Slaymaker, Radek Slupik, Mike Small, Benjamin Smith, Melvin Smith, Tim Smith, Adrian White aka snarkyboojum, Richard Soderberg, SolidState, Vishal Soni, Syloke Soong, Shawn Sorichetti, Tadeusz Sośnierz, sue spence, Cory Spencer, Robert Spier, Michael Stapelberg, Edwin Steiner, stephenpollei, Michael Stevens, Don Stewart, Radu Stoica, Klaas‑Jan Stol, Alek Storm, David Storrs, Mark Stosberg, Jonathan Stowe, Cosimo Streppone, Jonathan Strickland, Pascal Stumpf, Su‑Shee, Sue, Laye Suen, Dan Sugalski, Mark Summerfield, Simon Sun, Cheng‑Lung Sung 宋政隆, Sunnavy, Samuel Sutch, svatsan, svn, Andrew Sweger, sygi, Sebastian Sylvan, Gábor Szabó, Bálint Szilakszi, Marek Šuppa, TOGoS, Arvindh Rajesh Tamilmani, Audrey Tang 唐鳳, Bestian Tang 唐宗浩, Adrian Taylor, Jesse Taylor, Philip Taylor, Kevin Tew, the_dormant, Marcus Thiesen, Adam Thomason, Richard Tibbetts, Carey Tilden, Marcel Timmerman, Leon Timmermans, tkob, John Tobey, Frank Tobin, Bennett Todd, Graham Todd, Leopold Tötsch, Daniel Toma, Nathan Torkington, Timothy Totten, John J. Trammell, Matt S. Trout, Nat Tuck, Adam Turoff, Ben Tyler, ujwal, Bernd Ulmann, Reini Urban, parrot user, uzair, VZ, Ilmari Vacklin, vamped, Wim Vanderbauwhede, vendethiel, David Vergin, Ted Vessenes, Sam Vilain, Cédric Vincent, Jesse Vincent, Jos Visser, John van Vlaanderen, vmax, Jeremy Voorhis, Martin Vorländer, Johan Vromans, Maxim Vuets, Juerd Waalboer, Mariano Wahlmann, Kevin Walker, Gloria Wall, Larry Wall, Lewis Wall, Michal J Wallace, John Paul Wallington, walter, Matthew Walton, Ting Wang, Xinyuan Wang, Andy Wardley, Bryan C. Warnock, wayland, Stephen Weeks, Zhen‑Bang Wei, Nick Wellnhofer, Shu‑Chun Weng, Danny Werner, Brian Wheeler, David E. Wheeler, Dave Whipp, Adrian White, Andrew Whitworth, Bart Wiegmans, Nathan Wiger, Brock Wilcox, Edwin Wiles, Bob Wilkinson, Chris ‘BinGOs’ Williams, Greg Williams, Josh Wilmes, Matthew Wilson, Ashley Winters, Brian Wisti, Dave Woldrich, Helmut Wollmersdorfer, Kevin J. Woolley, Jonathan Worthington, Kuang‑Che Wu 吳光哲, xenu, Liang‑Qi Xie 謝良奇, Xtreak, Gaal Yahas גל יחס, Thomas Yandell, Alvis Yardley, Thomas Yeh 葉志宏, Natan Yellin, yiyihu, Matt Youell, Tony Young, Shen, Yu‑Teh, Ilya Zakharevich, Ruslan Zakirov, Ahmad M. Zawawi, Michael A. D. Zedeler, zengargoyle, zeriod, Agent Zhang 章亦春, Jimmy Zhuo, Ziggy6, Rob Zinkov, Zoffix Znet

If you would like to contribute or find out more information, visit
http://perl6.org, http://rakudo.org/how-to-help, ask on the
perl6-compiler@perl.org mailing list, or ask on IRC #perl6 on freenode.

The next release of Rakudo (#95), is tentatively scheduled for 16 January 2016. A list of the other planned release dates is available in the “docs/release_guide.pod” file.

The development team appreciates feedback! If you’re using Rakudo, do get back to us. Questions, comments, suggestions for improvements, cool discoveries, incredible hacks, or any other feedback — get in touch with us through (the above-mentioned) mailing list or IRC channel. Enjoy!

[^1]: See http://moarvm.org/

[^2]: See https://en.wikipedia.org/wiki/Koliada

[^3]: See https://github.com/perl6/roast/tree/6.c

[^4]: What’s the difference between the Rakudo compiler and the Rakudo Star distribution?

The Rakudo compiler is a compiler for the Perl 6 language. Not much more.

The Rakudo Star distribution is the Rakudo compiler plus a selection of useful Perl 6 modules, a module installer, the most recent incarnation of the “Using Perl 6” book, and other software that can be used with the Rakudo compiler to enhance its utility. Rakudo Star is meant for early adopters who wish to explore what’s possible with Rakudo Perl 6 and provide feedback on what works, what doesn’t, and what else they would like to see included in the distribution.

Day 24 – An Unexpectedly Long-expected Party

Camelia-small

Hello. Ting, ting, ting. Attention! … ATTENTION!

Thank you.

Hi, I’m Camelia, if you don’t know me. (Or even if you do.) They told me I had to give a speech at Perl 6’s official Coming Out Party. So here I am. Someone else is doing the roast. I’m just the toast. They told me it had to be a serious speech. Ha, like I’d know how to give a serious speech. Seriously?

Well. Seriously, I’d like to thank you all for coming out today.

Oops, I guess that was a pun. Sorry. Well, no, not really…

But thanks for showing up. This is a big day for Perl 6. She is officially of age now. Well, kinda sorta. She has her driver’s license, anyway. Watch out, world!

[inaudible comment from a table in back]

Oh, should I not have mentioned that? I wasn’t really talking about those fender benders she had while… Well, anyway, let’s move on. I’m sure she’ll be a really good driver. From now on.

Anyway, I have a great deal of empathy for Perl 6, because I am a butterfly. I too had to spend Far Too Long as a chrysalis before I had my own coming out. A literal coming out in my case. Hah, a literal coming out FROM my case, I should say!

Er, oops. I did it again, didn’t I.

Anyway, please be patient with Perl 6. Today we declare her to be a relatively competent being, but she is still just a teenager, y’know. When we’re very young, we’re just the age we are, but when we get to be teenagers, and go through all these hormonal changes, well, we start to oscillate. And the swings just get wider for a while. So when you’re 15, the swing is like plus-or-minus 10 years. One day you’ll act like you’re 25, and the next day like you’re 5 again.

So Perl 6 still has some maturing to do, fershure. That doesn’t mean we don’t love her any less on the days she’s throwing tantrums and driving us crazy. It just means, well, I guess it just means she’s family, and you love family through thick and thin. Because you trust family to turn thin back into thick someday.

And we’re all her extended family, gathered here today. They say it takes a village to raise a child. But never has there been such a child, or such a village! When you get a chance to look at your program tomorrow after your hangover wears off, just look at the list of benefactors in back. There are over 800 names of people who actively contributed to the development of Perl 6, one way or another. And undoubtedly there are a few names missing from the list.

You are a great bunch of people. All of you. Not just the closest members of the family. The family realized long ago that some of the most valuable guidance a growing computer language can get comes from outside the immediate family. It comes from friends and acquaintances who can have more perspective than someone who is always close. That’s why it takes a village.

Maturity is a fractal entity, and operates on many different scales. You all have been a proxy for the wide, wide world that Perl 6 is going out into. And it’s a rough world out there. Perl 6 is ready for some of it, thanks to you.

Of course, she’s still just 15. She does some things really well now. Her communication skills are pretty good, and she is very polite when she can’t understand you. She can carry on several conversations at once. She’s getting pretty good at math, and shows skill in manipulating objects of various sorts. She loves foreign languages, and all those funny characters.

But she’s still a deliberate child, and sometimes seems to be thinking too hard when learning something. That’s okay. She’ll get faster and more efficient over the next several years, as her brain rewires itself into full adulthood. She’ll learn new things, about the world and about herself. But I don’t think her personality will change much, that’s pretty obvious by now.

And that’s because her personality really comes from all of you. You’ve all loved her into existence, and now she’s ready to pass that love on to others who haven’t met her yet.

We all get really excited when a rocket takes off. TimToady tells me about getting up in the wee hours of the morning to watch Mercury, Gemini, and Apollo rockets take off. I’m too young to remember those, but we have our own thrilling developments to track. Me, I was very happy to see a SpaceX rocket stick its landing this week. After several fender benders…

[another inaudible comment]

I’m ignoring you. Be careful. We’ve gotten really, really good at ignoring certain kinds of people. Don’t be one of them.

Really, I feel sorry for the people who are only happy when they have something to be unhappy about.

Anyway, launching Perl 6 into the world is a lot like a rocket launch. A lot of excitement during the countdown, that hold-your-breath moment when you wonder if it’s really going to go up or explode. That’s where we are now. The main engines are lit, the clamps are letting go. It’s all very dramatic, mostly because nothing much seems to be happening right now.

But that’s not what a rocket is about. Drama is not what a rocket wants to do. A rocket wants to go up, faster and faster and faster. It’s not about position. It’s not really even about velocity. It’s about acceleration.

[raises glass]

So, I give you Perl 6. She is free to fly. May she have joy in her existence. May she have joy in discovering the world. May she accelerate as long as she will! Cheers!