Slash Boxes
NOTE: use Perl; is on undef hiatus. You can read content, but you can't post it. More info will be forthcoming forthcomingly.

All the Perl that's Practical to Extract and Report

use Perl Log In

Log In

[ Create a new account ]

dpuu (6090)

  (email not shown publicly)
Yahoo! ID: dave_whipp (Add User, Send Message)

Journal of dpuu (6090)

Tuesday December 23, 2008
02:40 PM

My first experiment with Perl6

[ #38142 ]
So Patrick suggested on that playing with Microsoft's "Winter Scripting Games" would be a good way to get started with Rakudo.

I liked that idea, so I went to the first challenge (for beginners) -- simply count the number of pairs in a list. For their test data (7,5,7,7,13), the correct answer is to be "3", because "7" is paired 3 different ways.

I immediately thought of the new cross-product operator:

my @x = < 7 5 7 7 13 >;
say for @x X~X @x;

Here I found my first p6 gotcha. In perl5, "say for @x" will print the values of @x, one per line. In P6, $_ is not implicit in a function call to the builtins: you need to use a method call:

.say for @x X~X @x;

For something to be a pair, the two values will be the same. So what I need to do is to count the number of combinations of elements for which the value is the same:

say ((@x X==X @x).grep:{ $^same }).elems;

This works, but the result is way too big. The X==X operator counts every pairing twice; plus every element is paired with itself. We need to adjust the result:

say ((( @x X==X @x ).grep: { $^same }).elems - @x.elems)/2;

This indeed prints the correct answer. And it nicely shows the power of P6. But it also suggests that more power is needed. The need to adjust the result to eliminate duplicates is bad. What is really needed is an operator that crosses every element of a list with each element that is to its right in the original list -- what I might call a diagonal cross.

I need to figure out how to define such a meta-operator in P6 -- and then figure out how to implement it in Rakudo! If my diagonal-cross was defined, say, using "%==%" then the implementation of the original challenge would become:

say ((@x %==% @x).grep: { $^same }).elems

That would be truly awesome and, to my mind, elegant!

The Fine Print: The following comments are owned by whoever posted them. We are not responsible for them in any way.
More | Login | Reply
Loading... please wait.
  • I went off of your examples and fiddled around a bit more with a reduction operator, and came up with this:

    say (([+] @x XeqX @x) - @x.elems)/2;

    It appears to work, and doesn't require the diagonal cross operator. The diagonal cross operator does seem like it would be a nice tool to have, tho' :-)
    • Having thought it through, my "diagonal cross" should almost certainly be prefix, not infix -- I can't think what a diagonal cross with a different array would mean. So:

      say [+] %eq% @x

      if I can figure out how to implement it!