Skip to content
A gem for adding functional programming tools to Ruby. Inspired by Erlang, Clojure, Haskell, and Functional Java.
Branch: master
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Type Name Latest commit message Commit time
Failed to load latest commit information.
doc Update block argument docs for pattern-match Sep 24, 2015
lib fix Protocol documentation typo Jan 9, 2018
tasks Added rake tasks for publishing docs to GitHub pages. Feb 25, 2015
.coveralls.yml Added coveralls for code coverage reporting. Sep 8, 2013
.gitignore Added .rspec-local to .gitignore file. Feb 25, 2015
.rspec Add `.rspec` file Feb 23, 2015
.yardopts Remove `doc/*.md` files from yard processing Feb 23, 2015 Added code of conduct. Oct 12, 2015
Gemfile Updated gem dependencies. Jan 9, 2018
LICENSE Initial commit May 4, 2013 Added AppVeyor for CI on Windows. Jul 10, 2015
Rakefile Updated yard setup. Jul 8, 2014
appveyor.yml Added AppVeyor for CI on Windows. Jul 10, 2015
functional_ruby.gemspec Updated min Ruby version and all required gem versions. Apr 17, 2015

Functional Ruby

Gem Version Travis CI Build Status AppVeyor Build status Coverage Status Code Climate Inline docs Dependency Status License

A gem for adding functional programming tools to Ruby. Inspired by Erlang, Clojure, and Functional Java.


Two things I love are Ruby and functional programming. If you combine Ruby's ability to create functions sans-classes with the power of blocks, proc, and lambda, Ruby code can follow just about every modern functional programming design paradigm. Add to this Ruby's vast metaprogramming capabilities and Ruby is easily one of the most powerful languages in common use today.


Our goal is to implement various functional programming patterns in Ruby. Specifically:

  • Be an 'unopinionated' toolbox that provides useful utilities without debating which is better or why
  • Remain free of external gem dependencies
  • Stay true to the spirit of the languages providing inspiration
  • But implement in a way that makes sense for Ruby
  • Keep the semantics as idiomatic Ruby as possible
  • Support features that make sense in Ruby
  • Exclude features that don't make sense in Ruby
  • Keep everything small
  • Be as fast as reasonably possible


The primary site for documentation is the automatically generated API documentation.

  • Protocol specifications inspired by Clojure protocol, Erlang behavior, and Objective-C protocol.
  • Function overloading with Erlang-style function pattern matching.
  • Simple, thread safe, immutable data structures, such as Record, Union, and Tuple, inspired by Clojure, Erlang, and other functional languages.
  • Thread safe, immutable Either and Option classes based on Functional Java and Haskell.
  • Memoization of class methods based on Clojure memoize.
  • Lazy execution with a Delay class based on Clojure delay.
  • ValueStruct, a simple, thread safe, immutable variation of Ruby's OpenStruct class.
  • Thread safe data structures, such as FinalStruct and FinalVar, which can be written to at most once before becoming immutable. Based on Java's final keyword.

Supported Ruby Versions

MRI 2.0 and higher, JRuby (1.9 mode), and Rubinius 2.x. This library is pure Ruby and has no gem dependencies. It should be fully compatible with any interpreter that is compliant with Ruby 2.0 or newer.


gem install functional-ruby

or add the following line to Gemfile:

gem 'functional-ruby'

and run bundle install from your shell.

Once you've installed the gem you must require it in your project:

require 'functional'


Specifying a protocol:

Functional::SpecifyProtocol(:Name) do
  attr_accessor :first
  attr_accessor :middle
  attr_accessor :last
  attr_accessor :suffix

Defining immutable data structures including Either, Option, Union and Record

Name =, :middle, :last, :suffix) do
  mandatory :first, :last
  default :first, 'J.'
  default :last, 'Doe'

anon = #=> #<record Name :first=>"J.", :middle=>nil, :last=>"Doe", :suffix=>nil>
matz = 'Yukihiro', last: 'Matsumoto') #=> #<record Name :first=>"Yukihiro", :middle=>nil, :last=>"Matsumoto", :suffix=>nil>

Pattern matching using protocols, type checking, and other options:

class Foo
  include Functional::PatternMatching
  include Functional::Protocol
  include Functional::TypeCheck

  def greet
    return 'Hello, World!'

  defn(:greet, _) do |name|
    "Hello, #{name}!"

  defn(:greet, _) { |name|
    "Pleased to meet you, #{name.full_name}!"
  }.when {|name| Type?(name, CustomerModel, ClientModel) }

  defn(:greet, _) { |name|
    "Hello, #{name.first} #{name.last}!"
  }.when {|name| Satisfy?(name, :Name) }

  defn(:greet, :doctor, _) { |name|
    "Hello, Dr. #{name}!"

  defn(:greet, nil, _) { |name|
    "Goodbye, #{name}!"

  defn(:greet, _, _) { |_, name|
    "Hello, #{name}!"

Performance improvement of idempotent functions through memoization:

class Factors
  include Functional::Memo

  def self.sum_of(number)

  def self.of(number)
    (1..number).select {|i| factor?(number, i)}

  def self.factor?(number, potential)
    number % potential == 0



  1. Fork it
  2. Create your feature branch (git checkout -b my-new-feature)
  3. Commit your changes (git commit -am 'Add some feature')
  4. Push to the branch (git push origin my-new-feature)
  5. Create new Pull Request

License and Copyright

Functional Ruby is free software released under the MIT License.

You can’t perform that action at this time.