Quick Tip #28: Perl 6’s Schwartzian Transform

This is a really Quick Tip. It’s about the Schwartzian Transform, which makes things quicker.

You may have seen my presentation from the Alpine Perl Workshop 2016. I talked abou the surprisingly tense history of the Schwartzian Transform. I also wrote about it for PerlTricks.

In short, Randal didn’t invent it but he made it popular. The popularity wasn’t immediate though.

In Perl 5 that looks like this map-sort-map:

  map { $_->[0] }
  sort { $a->[1] <=> $b->[1] }
  map { [$_, lc] }

The trick is to reduce the number of time you call lc. There’s no need to call it over and over on the same string.

How would you do the same thing in Perl 6?

First, Perl 6 has a unary version of sort. I tell it how to make a value then it does that for each pair of elements to compare:

my @sorted_words = sort { .lc }, @words;

It takes two elements from the list, lowercases both of them, and compares them with string equality (cmp). You don’t have to type out the .lc twice. This doesn’t transform the elements, so the output list isn’t necessarily all lowercase. It’s the original list but possibly re-ordered.

Not only that, sort caches the result of the operation so it doesn’t have to redo it. That is, Perl 6 already does what the Schwartzian Transform was doing!

One comment

  1. Any code block or sub will do: so you don’t need to make a code block *and* call .lc in there. You can just pass the sub directly:

    my @sorted_words = sort &lc, @words;

Leave a Reply

Your email address will not be published. Required fields are marked *