Cookie Notice

As far as I know, and as far as I remember, nothing in this page does anything with Cookies.

2011/03/16

The Schwartzian Mindset

Yeah, but your scientists were so preoccupied with whether or not they could, they didn't stop to think if they should. Dr. Ian Malcolm

I have recently come to a knowledge of the power of map and grep when dealing with hashes and arrays of data.

The key to entering this mindset is the Schwartzian Transform. Here is a canonical example.
@sorted = map  { $_->[0] }
          sort { $a->[1] cmp $b->[1] }
          map  { [$_, foo($_)] }
               @unsorted;
For years, I looked at that and said "Huh?", then wrote for my $i ( @unsorted ) { ... } or something like that. In fact, let's look at a for-loop implementation that would get similar results.
my @sorted ;
for my $i ( @unsorted ) {
          my $j = foo($i) ;
          $hash{$j} = $i ;
          }
for my $k ( sort { $a cmp $b } keys %hash ) {
          push @sorted , $hash{ $k } ;
          }

That's a lot more code, and it would not surprise me at all if my code was far slower than the Wikipedia example code, but I understood for loops from my first year of programming, so I can look at the second example and immediately understand it, and would still understand it if I came back and looked at it in a month.

Of course, you can comment this sort of thing to explain it to your later self.
@sorted = map  { $_->[0] } # taking away the sorting field
          sort { $a->[1] cmp $b->[1] } #sorting by the 2nd field in the anonymous arrays
          map  { [$_, foo($_)] } # an array of 2-element anonymous arrays
               @unsorted; # the original unsorted array 

I find myself using the map and grep method a lot lately. It avoids a lot of extra arrays floating around, but as I looked at the Schwartzian Transform and boggled for years, I could see myself, or the next person holding this seat, looking at the code for hours and failing to get it. But at least, now that I can code like that, I can wonder if I should...

5 comments:

  1. ""I could see myself, or the next person holding this seat, looking at the code for hours and failing to get it. But at least, now that I can code like that, I can wonder if I should...""

    You definitely can, and should. :)
    The more you use Perl, the more comfortable you will be with map, grep, and sort.
    You will look at a long chain of them and immediately understand what they're doing, and why they're doing it.

    To an experienced Perl developer, they're actually a lot EASIER to read than a bunch of 'for' loops. So keep at it, and it will be second nature.

    ReplyDelete
  2. The value of the Schwartzian Transform is that it encapsulates a complex concept in a simple meme.

    The underlying concept is "efficiently sort a list by a calculated value".

    Calling that a "Schwartzian Transform" and implementing it in a consistent way increases the abstraction level of your code.

    Of course, this is really a hackaround for an insufficiently power language. What we really want is for the Perl interpreter to recognize what we're doing and implement the caching for us.

    ReplyDelete
  3. The best explanation of the Schwartzian Transform is from Joseph Hall. It's in either edition of Effective Perl Programming. It's the excellent writing that allows people to finally grok it.

    ReplyDelete
  4. I agree with brian. After reading _Effective Perl Programming_ I was able to grok what the Schwartzian Transform was doing...and then extend that idiom to other list/array based operations.

    ReplyDelete
  5. Ofcourse, in this specific case rather than manually writing the Schwartzian yourself, you could just:

    use List::UtilsBy 'sort_by';

    @sorted = sort_by { foo($_) } @unsorted;

    ReplyDelete