website stat

Haskell’s foldr and foldl in… Ruby

I've found this very interesting snippet on how to implement the Haskell (and general FP methods) foldr() and foldl() in Ruby. Enjoy. It will spare you tons of confusing and error-prone lines dealing with Enumerable objects.

RUBY:
  1. module Enumerable
  2. def foldr(o, m = nil)
  3. reverse.inject(m) {|m, i| m ? i.send(o, m) : i}
  4. end
  5.  
  6. def foldl(o, m = nil)
  7. inject(m) {|m, i| m ? m.send(o, i) : i}
  8. end
  9. end
  10.  
  11. [1, 2, 3, 4, 5].foldl(:+) #=> 15
  12. [1, 2, 3, 4, 5].foldl(:*) #=> 120
  13.  
  14. [1, 2, 3, 4, 5].foldr(:-, 0) #=> 3
  15. [1, 2, 3, 4, 5].foldl(:-, 0) #=> -15


2 Responses to “Haskell’s foldr and foldl in… Ruby”

  1. Carlos Rodrigues
    Published at June 9th, 2007 at 1:24 pm

    import operator

    a = [1,2,3,4,5]

    sum(a) # 15
    reduce(operator.mul, a) # 120
    reduce(operator.sub, a) # 3
    reduce(operator.sub, reversed(a)) # -15

    BTW, I’m not trying to get into the Python vs. Ruby discussion here… Doesn’t Ruby have sum/reduce too?

    I think this is clearer, and it’s faster too… ;)

  2. mlopes
    Published at June 9th, 2007 at 10:50 pm

    Carlos,

    Ruby does not have an explicit reduce or sum function, both easily implemented using inject().

    As for being faster I honestly don’t know. Does Python have tail-call optimization? Otherwise those fold actions would be linear

    Hmm it does not seem to have but there are ways around it

    http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/474088

    But Ruby doesn’t have tail-call optimization too.