Thursday, March 12, 2009

Speaking of Perl, Ruby and sorting, sort in both Perl and Ruby allow you to specify a code block to implement your own arbitrary sorting routine. Perl's documentation shows you how you can define this as a subroutine and just reference the subroutine when you call sort. This is handy both for re-use and when your sort routine is complex and doesn't easily fit on one line. Ruby's sort documentation? Eh, no mention of such a thing.

In fact it is possible, but delves into a whole area of Ruby that is somewhat under-documented. The trick is that sort wants a code block, but code blocks are not first class entities. You can't name and reference a code block. However, Ruby has a couple of similar entities, Proc and lambda, that can be converted to/from code blocks and can be named and referenced. The unary ampersand operator will convert a Proc or lambda to a code block. The syntax works like this:

names = [
  {:fname => 'John', :lname => 'Smith'},
  {:fname => 'Jane', :lname => 'Smith'} ]


sorter = lambda do |a,b|
  [a[:lname], a[:fname]] <=> [b[:lname], b[:fname]]
end

names.sort(&sorter)

No comments: