## Idioms

I’ve contrived to do a good bit of \$work programming in Perl 6 over the last few weeks, and I’ve been forced to develop a few new (or at least, new to me) idioms in the process. In particular, here’s one I mentioned on #perl6:

sub length(@points) {
[+] (1 ..^ +@points).map({distance(@points[\$_], @points[\$_ - 1])});
}

Frequently in geometry you have to do something like this, where you have an array of items, and must compare each item in the list to the next. Initially I floundered around with code that looked something like this:

sub length(@points) {
for @points.keys -> \$i {
next if \$i == 0;
distance(@points[\$_], @points[\$_ - 1])
}
}

(Yes, that version doesn’t actually sum the distances, but you get the idea.) This is essentially trying to translate C++ idioms to Perl 6. The version at the top of the page is clearly better, and I was pleased with myself for working it out.

That said, it occurs to me that it would probably be better to do something like this:

sub pair-with-next(Iterable \$a-iterable) {
my \$ai = \$a-iterable.iterator;
my \$previous = \$ai.get;
return if \$previous ~~ EMPTY;
gather loop {
my \$current = \$ai.get;
last if \$current ~~ EMPTY;
take \$previous;
take \$current;
\$previous = \$current;
}
}

(WARNING: This is completely untested code!) With that defined, you’d just say something like

sub length(@points) {
[+] pair-with-next(@points).map(-> \$a, \$b {distance(\$a, \$b)});
}

That feels much cleaner to me than the first version, and has the advantage that it can work on iterators as well as Seq/Arrays.

### 2 Responses to “Idioms”

1. Eevee Says:

My Perl 6 is a little outdated, but couldn’t you just do:

sub length(@points) {
[+] (@points Z @points[1..*]).map: distance(*\$_)
}

• colomon Says:

Almost, I don’t think distance(*\$_) will quite do it. But yes, your general point of using Z like that is dead on. That idiom doesn’t work in Rakudo at the moment, so it slipped my mind.