Hi, I'm looking for examples of functional code in ruby. Maybe you know some gems, where I can find such a code?
Have you looked at Enumerable?
(1..100).select { |i| i % 5 == 0 }.map { |i| i * 5 }.take(3) #=> [25, 50, 75]
You might be interested in the talk "Better Ruby through Functional Programming" by Dean Wampler, it shows how to use a FP style with Ruby:
There's also "Thinking functionally in Ruby" by Tom Stuart:
A couple of months ago, I wondered whether it was possible to make a mixin that behaves exactly like Enumerable
, but is based on folding instead of enumerating. Or more precisely, I already knew that it was possible to do this, since fold is a generic iteration operation that is equal in expressive power to foreach, but I wanted to know what it would look like and how hard it would be.
I got bored after I had implemented most methods up to the letter g, so it's incomplete. Also, the version I show here is simplified, since making it behave exactly like Enumerable
is a PITA in Ruby. (For example, there are overloaded methods in there, but Ruby doesn't support overloading. This isn't a problem for most Ruby implementations, because they implement Enumerable
in Java or C# or other languages that do support overloading, but it is pretty painful when doing it in pure Ruby, so I decided to leave it out.)
Enumerable
is full of higher-order procedures, and of course fold (or reduce
/ inject
as it is called in Ruby) is itself a higher-order procedure, so this code is full of them.
module Enumerable
def all?
reduce(true) {|res, el| res && yield(el) }
end
def any?
reduce(false) {|res, el| res || yield(el) }
end
def collect
reduce([]) {|res, el| res + yield(el) }
end
alias_method :map, :collect
def count
reduce(0) {|res, el| res + 1 if yield el }
end
def detect
reduce(nil) {|res, el| if yield el then el end unless res }
end
alias_method :find, :detect
def drop(n=1)
reduce([]) {|res, el| res.tap {|res| res + el unless n -= 1 >= 0 }}
end
def each
reduce(nil) {|_, el| yield el }
end
def each_with_index
reduce(-1) {|i, el| (i+1).tap {|i| yield el, i }}
end
def find_all
reduce([]) {|res, el| res.tap {|res| res + el if yield el }}
end
alias_method :select, :find_all
def grep(pattern)
reduce([]) {|res, el| res.tap {|res| res + yield(el) if pattern === el }}
end
def group_by
reduce(Hash.new {|hsh, key| hsh[key] = [] }) {|res, el| res.tap {|res|
res[yield el] << el
}}
end
def include?(obj)
reduce(false) {|res, el| break true if res || el == obj }
end
def reject
reduce([]) {|res, el| res.tap {|res| res + el unless yield el }}
end
end
You will notice that I use side-effects in some places. I could have written it without side-effects instead, but it would have been much more complicated. And the problem is that there is no way for me to ensure that the reduce
method, which is provided by the client of the mixin, or any of the methods from the core library, don't have side-effects.
Another nice example is the Prelude library for Ruby, which is an implementation of some parts of the Haskell Prelude (Haskell's equivalent to Ruby's core library) in Ruby.
"The Ruby Programming Language" has half a chapter where they work on a couple of additions to enumerable to make ruby look like Haskell.
You may also want to browse previous Stack Overflow questions tagged with both "Ruby" and "functional-programming" here.