Glad You're Ready. Let's Get Started!

Let us know how we can contact you.

Thank you!

We'll respond shortly.

  • Blog Navigation
Functional witness protection

I wrote a bit about function objects here. However, if you don’t buy that the persistent state of function objects provides something that anonymous functions cannot, how about this: readability. In some cases.

Anonymous functions are boss and cool, and extremely common in idiomatic Ruby. However, in some cases they can get a little… esoteric. Consider:

people.sort do |lhs, rhs|
  lhs, rhs = rhs, lhs if ascending?
  result = <=>
  if result == 0
    result = lhs.date_of_birth <=> rhs.date_of_birth

 # etc...

Sometimes, anonymity isn’t the answer. Consider:

class ByNameAscending
  def self.to_proc { |lhs, rhs| <=> }

This allows you to write this:


Or, to push the example to the extreme:

class SortOrder
  def initialize(direction = :descending)
    @direction = direction

  def by(attribute)
    attributes << attribute
  alias_method :and, :by

  def to_proc do |lhs, rhs|
      lhs, rhs = rhs, lhs if ascending?

      return lhs <=> rhs if attributes.empty?
      attributes.each do |attribute|
        result = lhs.send(attribute) <=> rhs.send(attribute)
        return result if result != 0


  def attributes
    @attributes ||= []

  def ascending?
    @direction == :ascending

def ascending;; end

Which gives us:


A DSL for generating sort order function objects. It could be useful.

  1. grosser says:

    i really like the syntax of people.sort(&

    Did you consider using sort_by? It would be faster and easier to write.

  2. Steve Conover says:

    Very cool

  3. Adam Milligan says:

    You’re absolutely right that #sort_by would simplify this function. To be honest, I tried to come up with an example with a fair bit of complexity in the proc in order to illustrate the readability improvements of using a function object, and it ended up being a bit contrived. A function that does something to circumvent # would have been better, although I can’t think of anything even vaguely reasonable at the moment.

    And, thinking about it just for a moment, I can’t think of a good way to make the syntax read as nicely with #sort_by.

    I’m bad at examples, but hopefully the general idea makes sense. I’m always interested to know of any real-world instances where this sort of thing turned up useful.

  4. Mark Wilden says:


    attributes.collect { |attribute| lhs.send(attribute) } attributes.collect { |attribute| rhs.send(attribute) }

    instead of

    attributes.each do |attribute|
    result = lhs.send(attribute) rhs.send(attribute)
    return result if result != 0

    It demonstrates that you can sort on multiple attributes by slapping them in an array.

    It’s probably worse than the original, but it *is* one line of code. :)

Post a Comment

Your Information (Name required. Email address will not be displayed with comment.)

* Copy This Password *

* Type Or Paste Password Here *

Share This