Composing functions in Ruby

Posted by Tom Moertel Fri, 07 Apr 2006 15:55:00 GMT

One of the things I miss when coding in Ruby is inexpensive function composition. In Haskell, for example, I can compose functions using the dot (.) operator:

inc        = (+1)
twice      = (*2)
twiceOfInc = twice . inc
Because of Ruby’s open classes, however, I can easily add the feature to the language. In the code below, I introduce Proc.compose and overload the star (*) operator for the purpose:
# func_composition.rb
class Proc
  def self.compose(f, g)
    lambda { |*args| f[g[*args]] }
  end
  def *(g)
    Proc.compose(self, g)
  end
end

And that’s all it takes:

$ irb --simple-prompt -r func_composition.rb

>> inc = lambda { |x| x + 1 }
=> #<Proc:0x00002aaaaaad7810@(irb):1>

>> twice = lambda { |x| x * 2 }
=> #<Proc:0x00002aaaaabd2d18@(irb):2>

>> inc[1]
=> 2

>> twice[2]
=> 4

>> twice_of_inc = twice * inc
=> #<Proc:0x00002aaaaab32458@./func_composition.rb:3>

>> twice_of_inc[1]
=> 4

>> twice_of_inc[2]
=> 6

Now, isn’t that refreshing?

Update: Vincent Foley pointed out on comp.lang.ruby that Ruby Facets has a nearly identical implementation that also uses the star operator for composition. (Its version of compose, however, is an instance method whereas my version is a class method.)

Posted in ,
Tags , ,
2 comments
no trackbacks
Reddit Delicious

Comments

  1. Peter said 332 days later:

    Thanks for this, Tom. I hope to see more Haskell constructs translated to Ruby in the future!

  2. TaQ said 521 days later:

    Hi there!

    I think you’d like to see something I did based on the problem described here:

    http://eustaquiorangel.com/blog/show/460

    It’s a Brazilian Portuguese post but the code speaks for itself. :-)

    Best regards,

Trackbacks

Use the following link to trackback from your own site:
http://blog.moertel.com/articles/trackback/62

(leave url/email »)

   Comment Markup Help Preview comment