Full Code of jdantonio/functional-ruby for AI

master fc99f555f03d cached
59 files
269.2 KB
71.8k tokens
339 symbols
1 requests
Download .txt
Showing preview only (286K chars total). Download the full file or copy to clipboard to get everything.
Repository: jdantonio/functional-ruby
Branch: master
Commit: fc99f555f03d
Files: 59
Total size: 269.2 KB

Directory structure:
gitextract_u_5mpmcl/

├── .coveralls.yml
├── .gitignore
├── .rspec
├── .travis.yml
├── .yardopts
├── CHANGELOG.md
├── CODE_OF_CONDUCT.md
├── Gemfile
├── LICENSE
├── README.md
├── Rakefile
├── appveyor.yml
├── doc/
│   ├── memo.md
│   ├── memoize.rb
│   ├── pattern_matching.md
│   ├── protocol.md
│   └── record.md
├── functional_ruby.gemspec
├── lib/
│   ├── functional/
│   │   ├── abstract_struct.rb
│   │   ├── delay.rb
│   │   ├── either.rb
│   │   ├── final_struct.rb
│   │   ├── final_var.rb
│   │   ├── memo.rb
│   │   ├── method_signature.rb
│   │   ├── option.rb
│   │   ├── pattern_matching.rb
│   │   ├── protocol.rb
│   │   ├── protocol_info.rb
│   │   ├── record.rb
│   │   ├── synchronization.rb
│   │   ├── tuple.rb
│   │   ├── type_check.rb
│   │   ├── union.rb
│   │   ├── value_struct.rb
│   │   └── version.rb
│   └── functional.rb
├── spec/
│   ├── .gitignore
│   ├── functional/
│   │   ├── abstract_struct_shared.rb
│   │   ├── complex_pattern_matching_spec.rb
│   │   ├── delay_spec.rb
│   │   ├── either_spec.rb
│   │   ├── final_struct_spec.rb
│   │   ├── final_var_spec.rb
│   │   ├── memo_spec.rb
│   │   ├── option_spec.rb
│   │   ├── pattern_matching_spec.rb
│   │   ├── protocol_info_spec.rb
│   │   ├── protocol_spec.rb
│   │   ├── record_spec.rb
│   │   ├── tuple_spec.rb
│   │   ├── type_check_spec.rb
│   │   ├── union_spec.rb
│   │   └── value_struct_spec.rb
│   ├── spec_helper.rb
│   └── support/
│       └── .gitignore
└── tasks/
    ├── .gitignore
    ├── metrics.rake
    └── update_doc.rake

================================================
FILE CONTENTS
================================================

================================================
FILE: .coveralls.yml
================================================
repo_token: M3JnILwxCIYb4OjWvyxBJkib9xsAGdnek


================================================
FILE: .gitignore
================================================
Gemfile.lock
.rspec-local
*.gem
lib/1.8
lib/1.9
lib/2.0
.rvmrc
.ruby-version
.ruby-gemset
.bundle/*
.yardoc/*
yardoc/*
tmp/*
man/*
*.tmproj
rdoc/*
*.orig
*.BACKUP.*
*.BASE.*
*.LOCAL.*
*.REMOTE.*
git_pull.txt
coverage
critic
.DS_Store
TAGS
tmtags
*.sw?
.idea
.rbx/*
lib/*.bundle
lib/*.so
lib/*.jar
ext/*.bundle
ext/*.so
ext/*.jar
pkg
*.gem


================================================
FILE: .rspec
================================================
--require spec_helper
--format progress


================================================
FILE: .travis.yml
================================================
language: ruby

rvm:
  - 2.2.3
  - 2.2.2
  - 2.2.1
  - 2.1.5
  - 2.1.4
  - 2.0.0
  - ruby-head
  - jruby-1.7.19
  - jruby-9.0.1.0
  - jruby-9.0.3.0
  - jruby-9.0.4.0
  - jruby-head
  - rbx-2

jdk:
  - oraclejdk8

sudo: false

branches:
  only:
    - master

matrix:
  allow_failures:
    - rvm: ruby-head
    - rvm: jruby-head
    - rvm: jruby-9.0.1.0
    - rvm: rbx-2

script: "CODECLIMATE_REPO_TOKEN=65d4787423f734f5cf6d2b3f9be88e481802e50af0879e8ed66971f972d70894 bundle exec rake"


================================================
FILE: .yardopts
================================================
--protected
--no-private
--embed-mixins
--output-dir ./yardoc
--markup markdown
--title=Functional Ruby
--template default

./lib/**/*.rb
-
README.md
CHANGELOG.md
LICENSE


================================================
FILE: CHANGELOG.md
================================================
## Current Release v1.3.0 (October 4, 2015)

* Pattern match now check arity of pattern and block
* `PatternMatching::ALL` pattern now should be presented as variable length args (*args)
* `NoMethodError` and `ArgumentError` raised from method block won't be catched anymore by lib

### Release v1.2.0 (July 10, 2015)

* `Record` classes can be declared with a type/protocol specification for type safety.
* Improved documentation
* Improved tests
* Better synchronization (thread safety) on all platforms
* Continuous integration run on both Linux (Travis CI) and Windows (AppVeyor)

### Release v1.1.0 (August 12, 2014)

* A simple implementation of [tuple](http://en.wikipedia.org/wiki/Tuple), an
  immutable, fixed-length list/array/vector-like data structure.
* `FinalStruct`, a variation on Ruby's `OpenStruct` in which all fields are "final" (meaning
  that new fields can be arbitrarily added but once set each field becomes immutable).
* `FinalVar`, a thread safe object that holds a single value and is "final" (meaning
  that the value can be set at most once after which it becomes immutable).

### Release v1.0.0 (July 30, 2014)

* Protocol specifications inspired by Clojure [protocol](http://clojure.org/protocols),
  Erlang [behavior](http://www.erlang.org/doc/design_principles/des_princ.html#id60128),
  and Objective-C [protocol](https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/ProgrammingWithObjectiveC/WorkingwithProtocols/WorkingwithProtocols.html)
* Function overloading with Erlang-style [function](http://erlang.org/doc/reference_manual/functions.html)
  [pattern matching](http://erlang.org/doc/reference_manual/patterns.html)
* Simple, immutable data structures, such as *record* and *union*, inspired by
  [Clojure](http://clojure.org/datatypes), [Erlang](http://www.erlang.org/doc/reference_manual/records.html),
  and [others](http://en.wikipedia.org/wiki/Union_type)
* `Either` and `Option` classes based on [Functional Java](http://functionaljava.org/) and [Haskell](https://hackage.haskell.org/package/base-4.2.0.1/docs/Data-Either.html)
* [Memoization](http://en.wikipedia.org/wiki/Memoization) of class methods based on Clojure [memoize](http://clojuredocs.org/clojure_core/clojure.core/memoize)
* Lazy execution with a `Delay` class based on Clojure [delay](http://clojuredocs.org/clojure_core/clojure.core/delay)


================================================
FILE: CODE_OF_CONDUCT.md
================================================
# Contributor Code of Conduct

As contributors and maintainers of this project, and in the interest of fostering an open and welcoming community, we pledge to respect all people who contribute through reporting issues, posting feature requests, updating documentation, submitting pull requests or patches, and other activities.

We are committed to making participation in this project a harassment-free experience for everyone, regardless of level of experience, gender, gender identity and expression, sexual orientation, disability, personal appearance, body size, race, ethnicity, age, religion, or nationality.

Examples of unacceptable behavior by participants include:

* The use of sexualized language or imagery
* Personal attacks
* Trolling or insulting/derogatory comments
* Public or private harassment
* Publishing other's private information, such as physical or electronic addresses, without explicit permission
* Other unethical or unprofessional conduct.

Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct. By adopting this Code of Conduct, project maintainers commit themselves to fairly and consistently applying these principles to every aspect of managing this project. Project maintainers who do not follow or enforce the Code of Conduct may be permanently removed from the project team.

This code of conduct applies both within project spaces and in public spaces when an individual is representing the project or its community.

Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by opening an issue or contacting one or more of the project maintainers.

This Code of Conduct is adapted from the [Contributor Covenant](http://contributor-covenant.org), version 1.2.0, available at [http://contributor-covenant.org/version/1/2/0/](http://contributor-covenant.org/version/1/2/0/)


================================================
FILE: Gemfile
================================================
source 'https://rubygems.org'

gemspec

group :development do
  gem 'rake', '~> 12.3.0'
end

group :testing do
  gem 'rspec', '~> 3.7.0'
  gem 'simplecov', '~> 0.14.1', platforms: :mri, require: false
  gem 'coveralls', '~> 0.8.21', require: false
end

group :documentation do
  gem 'countloc', '~> 0.4.0', platforms: :mri, require: false
  gem 'yard', '~> 0.9.12', require: false
  gem 'redcarpet', '~> 3.4.0', platforms: :mri # understands github markdown
end


================================================
FILE: LICENSE
================================================
Copyright (c) Jerry D'Antonio -- released under the MIT license.

http://www.opensource.org/licenses/mit-license.php  

Permission is hereby granted, free of charge, to any person obtaining a copy  
of this software and associated documentation files (the "Software"), to deal  
in the Software without restriction, including without limitation the rights  
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell  
copies of the Software, and to permit persons to whom the Software is  
furnished to do so, subject to the following conditions:  
 
The above copyright notice and this permission notice shall be included in  
all copies or substantial portions of the Software.  
 
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR  
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,  
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE  
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER  
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,  
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN  
THE SOFTWARE. 


================================================
FILE: README.md
================================================
# Functional Ruby
[![Gem Version](https://badge.fury.io/rb/functional-ruby.svg)](http://badge.fury.io/rb/functional-ruby)
[![Travis CI Build Status](https://secure.travis-ci.org/jdantonio/functional-ruby.png)](https://travis-ci.org/jdantonio/functional-ruby?branch=master)
[![AppVeyor Build status](https://ci.appveyor.com/api/projects/status/8xfy4a8lmc26112e/branch/master?svg=true)](https://ci.appveyor.com/project/jdantonio/functional-ruby/branch/master)
[![Coverage Status](https://coveralls.io/repos/jdantonio/functional-ruby/badge.png)](https://coveralls.io/r/jdantonio/functional-ruby)
[![Code Climate](https://codeclimate.com/github/jdantonio/functional-ruby.png)](https://codeclimate.com/github/jdantonio/functional-ruby)
[![Inline docs](http://inch-ci.org/github/jdantonio/functional-ruby.png)](http://inch-ci.org/github/jdantonio/functional-ruby)
[![Dependency Status](https://gemnasium.com/jdantonio/functional-ruby.png)](https://gemnasium.com/jdantonio/functional-ruby)
[![License](http://img.shields.io/license/MIT.png?color=green)](http://opensource.org/licenses/MIT)

**A gem for adding functional programming tools to Ruby. Inspired by [Erlang](http://www.erlang.org/),
[Clojure](http://clojure.org/), and [Functional Java](http://functionaljava.org/).**

## Introduction

Two things I love are [Ruby](http://www.ruby-lang.org/en/) and
[functional](https://en.wikipedia.org/wiki/Functional_programming)
[programming](http://c2.com/cgi/wiki?FunctionalProgramming).
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.

### Goals

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

## Features

The primary site for documentation is the automatically generated [API documentation](http://jdantonio.github.io/functional-ruby/).

* Protocol specifications inspired by Clojure [protocol](http://clojure.org/protocols),
  Erlang [behavior](http://www.erlang.org/doc/design_principles/des_princ.html#id60128),
  and Objective-C [protocol](https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/ProgrammingWithObjectiveC/WorkingwithProtocols/WorkingwithProtocols.html).
* Function overloading with Erlang-style [function](http://erlang.org/doc/reference_manual/functions.html)
  [pattern matching](http://erlang.org/doc/reference_manual/patterns.html).
* Simple, thread safe, immutable data structures, such as `Record`, `Union`, and `Tuple`, inspired by
  [Clojure](http://clojure.org/datatypes), [Erlang](http://www.erlang.org/doc/reference_manual/records.html),
  and other functional languages.
* Thread safe, immutable `Either` and `Option` classes based on [Functional Java](http://functionaljava.org/) and [Haskell](https://hackage.haskell.org/package/base-4.2.0.1/docs/Data-Either.html).
* [Memoization](http://en.wikipedia.org/wiki/Memoization) of class methods based on Clojure [memoize](http://clojuredocs.org/clojure_core/clojure.core/memoize).
* Lazy execution with a `Delay` class based on Clojure [delay](http://clojuredocs.org/clojure_core/clojure.core/delay).
* `ValueStruct`, a simple, thread safe, immutable variation of Ruby's [OpenStruct](http://ruby-doc.org/stdlib-2.0/libdoc/ostruct/rdoc/OpenStruct.html) 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](http://en.wikipedia.org/wiki/Final_(Java)).

### 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.

### Install

```shell
gem install functional-ruby
```

or add the following line to Gemfile:

```ruby
gem 'functional-ruby'
```

and run `bundle install` from your shell.

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

```ruby
require 'functional'
```

## Examples

Specifying a [protocol](http://rubydoc.info/github/jdantonio/functional-ruby/master/Functional/Protocol):

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

Defining immutable [data structures](http://rubydoc.info/github/jdantonio/functional-ruby/master/Functional/AbstractStruct) including
[Either](http://rubydoc.info/github/jdantonio/functional-ruby/master/Functional/Either),
[Option](http://rubydoc.info/github/jdantonio/functional-ruby/master/Functional/Option),
[Union](http://rubydoc.info/github/jdantonio/functional-ruby/master/Functional/Union) and
[Record](http://rubydoc.info/github/jdantonio/functional-ruby/master/Functional/Record)

```ruby
Name = Functional::Record.new(:first, :middle, :last, :suffix) do
  mandatory :first, :last
  default :first, 'J.'
  default :last, 'Doe'
end

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

[Pattern matching](http://rubydoc.info/github/jdantonio/functional-ruby/master/Functional/PatternMatching)
using [protocols](http://rubydoc.info/github/jdantonio/functional-ruby/master/Functional/Protocol),
[type](http://rubydoc.info/github/jdantonio/functional-ruby/master/Functional/TypeCheck) checking,
and other options:

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

  def greet
    return 'Hello, World!'
  end

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

  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}!"
  }
end
```

Performance improvement of idempotent functions through [memoization](http://rubydoc.info/github/jdantonio/functional-ruby/master/Functional/Memo):

```ruby
class Factors
  include Functional::Memo

  def self.sum_of(number)
    of(number).reduce(:+)
  end

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

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

  memoize(:sum_of)
  memoize(:of)
end
```

## Contributing

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](http://www.opensource.org/licenses/MIT).


================================================
FILE: Rakefile
================================================
$:.push File.join(File.dirname(__FILE__), 'lib')

GEMSPEC = Gem::Specification.load('functional-ruby.gemspec')

require 'bundler/gem_tasks'
require 'rspec'
require 'rspec/core/rake_task'

require 'functional'

Bundler::GemHelper.install_tasks

Dir.glob('tasks/**/*.rake').each do|rakefile|
  load rakefile
end

RSpec::Core::RakeTask.new(:spec) do |t|
  t.rspec_opts = '--color --backtrace --format documentation'
end

RSpec::Core::RakeTask.new(:travis_spec) do |t|
  t.rspec_opts = '--tag ~@not_on_travis'
end

task :default => [:travis_spec]


================================================
FILE: appveyor.yml
================================================
install:
  - SET PATH=C:\Ruby%ruby_version%\bin;%PATH%
  - SET PATH=C:\MinGW\bin;%PATH%
  - SET RAKEOPT=-rdevkit
  - ruby --version
  - gem --version
  - bundle install

build: off

test_script:
  - bundle exec rake

environment:
  matrix:
    - ruby_version: "200"
    - ruby_version: "200-x64"
    - ruby_version: "21"
    - ruby_version: "21-x64"
    - ruby_version: "22"
    - ruby_version: "22-x64"

#matrix:
  #allow_failures:
    #- ruby_version: "193"


================================================
FILE: doc/memo.md
================================================
# memoize

###    Rationale

   Many computational operations take a significant amount of time and/or use
   an inordinate amount of resources. If subsequent calls to that function with
   the same parameters are guaranteed to return the same result, caching the
   result can lead to significant performance improvements. The process of
   caching such calls is called
   [memoization](http://en.wikipedia.org/wiki/Memoization).

###    Declaration

   Using memoization requires two simple steps: including the
   `Functional::Memo` module within a class or module and calling the `memoize`
   function to enable memoization on one or more methods.

   ```ruby
   Module EvenNumbers
     include Functional::Memoize

     self.first(n)
       (2..n).select{|i| i % 2 == 0 }
     end

     memoize :first
   end
   ```

   When a function is memoized an internal cache is created that maps arguments
   to return values. When the function is called the arguments are checked
   against the cache. If the args are found the method is not called and the
   cached result is returned instead.

###    Ramifications

   Memoizing long-running methods can lead to significant performance
   advantages. But there is a trade-off. Memoization may greatly increase the
   memory footprint of the application. The memo cache itself takes memory. The
   more arg/result pairs stored in the cache, the more memory is consumed.

#####    Cache Size Options

   To help control the size of the cache, a limit can be placed on the number
   of items retained in the cache. The `:at_most` option, when given, indicates
   the maximum size of the cache. Once the maximum cache size is reached, calls
   to to the method with uncached args will still result in the method being
   called, but the results will not be cached.

   ```ruby
   Module EvenNumbers
     include Functional::Memoize

     self.first(n)
       (2..n).select{|i| i % 2 == 0 }
     end

     memoize :first, at_most: 1000
   end
   ```

   There is no way to predict in advance what the proper cache size is, or if
   it should be restricted at all. Only performance testing under realistic
   conditions or profiling of a running system can provide guidance.

###    Restrictions

   Not all methods are good candidates for memoization.Only methods that are
   [idempotent](http://en.wikipedia.org/wiki/Idempotence), [referentially
   transparent](http://en.wikipedia.org/wiki/Referential_transparency_(computer_science)),
   and free of [side effects](http://en.wikipedia.org/wiki/Side_effect_(computer_science))
   can be effectively memoized. If a method creates side effects, such as
   writing to a log, only the first call to the method will create those side
   effects. Subsequent calls will return the cached value without calling the
   method.

   Similarly, methods which change internal state will only update the state on
   the initial call. Later calls will not result in state changes, they will
   only return the original result. Subsequently, instance methods cannot be
   memoized. Objects are, by definition, stateful. Method calls exist for the
   purpose of changing or using the internal state of the object. Such methods
   cannot be effectively memoized; it would require the internal state of the
   object to be cached and checked as well.

   Block parameters pose a similar problem. Block parameters are inherently
   stateful (they are closures which capture the enclosing context). And there
   is no way to check the state of the block along with the args to determine
   if the cached value should be used. Subsequently, and method call which
   includes a block will result in the cache being completely skipped. The base
   method will be called and the result will not be cached. This behavior will
   occur even when the given method was not programmed to accept a block
   parameter. Ruby will capture any block passed to any method and make it
   available to the method even when not documented as a formal parameter or
   used in the method. This has the interesting side effect of allowing the
   memo cache to be skipped on any method call, simply be passing a block
   parameter.

   ```ruby
   EvenNumbers.first(100)         causes the result to be cached
   EvenNumbers.first(100)         retrieves the previous result from the cache
   EvenNumbers.first(100){ nil }  skips the memo cache and calls the method again
   ```

###   Complete Example

   The following example is borrowed from the book [Functional Thinking](http://shop.oreilly.com/product/0636920029687.do)
   by Neal Ford. In his book he shows an example of memoization in Groovy by
   summing factors of a given number. This is a great example because it
   exhibits all the criteria that make a method a good memoization candidate:

   * Idempotence
   * Referential transparency
   * Stateless
   * Free of side effect
   * Computationally expensive (for large numbers)

   The following code implements Ford's algorithms in Ruby, then memoizes two
   key methods. The Ruby code:

   ```ruby
   require 'functional'

   class Factors
     include Functional::Memo

     def self.sum_of(number)
       of(number).reduce(:+)
     end

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

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

     def self.perfect?(number)
       sum_of(number) == 2 * number
     end

     def self.abundant?(number)
       sum_of(number) > 2 * number
     end

     def self.deficient?(number)
       sum_of(number) < 2 * number
     end

     memoize(:sum_of)
     memoize(:of)
   end
   ```

   This code was tested in IRB using MRI 2.1.2 on a MacBook Pro. The `sum_of`
   method was called three times against the number 10,000,000 and the
   benchmark results of each run were captured. The test code:

   ```ruby
   require 'benchmark'

   3.times do
     stats = Benchmark.measure do
       Factors.sum_of(10_000_000)
     end
     puts stats
   end
   ```

   The results of the benchmarking are very revealing. The first run took over
   a second to calculate the results. The two subsequent runs, which retrieved
   the previous result from the memo cache, were nearly instantaneous:

   ```
   1.080000   0.000000   1.080000 (  1.077524)
   0.000000   0.000000   0.000000 (  0.000033)
   0.000000   0.000000   0.000000 (  0.000008)
   ```

   The same code run on the same computer using JRuby 1.7.12 exhibited similar
   results:

   ```
   1.800000   0.030000   1.830000 (  1.494000)
   0.000000   0.000000   0.000000 (  0.000000)
   0.000000   0.000000   0.000000 (  0.000000)
   ```

###    Inspiration

   * [Memoization](http://en.wikipedia.org/wiki/Memoization) at Wikipedia
   * Clojure [memoize](http://clojuredocs.org/clojure_core/clojure.core/memoize) function


================================================
FILE: doc/memoize.rb
================================================
#!/usr/bin/env ruby
$LOAD_PATH << File.expand_path('../../lib', __FILE__)

require 'functional'

class Factors
  include Functional::Memo

  def self.sum_of(number)
    of(number).reduce(:+)
  end

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

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

  def self.perfect?(number)
    sum_of(number) == 2 * number
  end

  def self.abundant?(number)
    sum_of(number) > 2 * number
  end

  def self.deficient?(number)
    sum_of(number) < 2 * number
  end

  memoize(:sum_of)
  memoize(:of)
end

require 'benchmark'
require 'pp'

def memory_usage
  `ps ax -o pid,rss | grep -E "^[[:space:]]*#{$$}"`.strip.split.map(&:to_i)
end

def print_memory_usage
  pid, size = memory_usage
  puts "Memory used by process #{pid} at #{Time.now} is #{size}"
end

def run_benchmark(n = 10000)

  puts "Benchmarks for #{n} numbers..."
  puts

  puts 'With no memoization...'
  stats = Benchmark.measure do
    Factors.sum_of(n)
  end
  puts stats

  2.times do
    puts
    puts 'With memoization...'
    stats = Benchmark.measure do
      Factors.sum_of(n)
    end
    puts stats
  end
end

if $0 == __FILE__
  run_benchmark(10_000_000)
end

__END__

$ ./doc/memoize.rb
Benchmarks for 10000000 numbers...

With no memoization...
  1.660000   0.000000   1.660000 (  1.657253)

With memoization...
  0.000000   0.000000   0.000000 (  0.000019)

With memoization...
  0.000000   0.000000   0.000000 (  0.000008)


================================================
FILE: doc/pattern_matching.md
================================================
###    Features

   * Pattern matching for instance methods.
   * Pattern matching for object constructors.
   * Parameter count matching
   * Matching against primitive values
   * Matching by class/datatype
   * Matching against specific key/vaue pairs in hashes
   * Matching against the presence of keys within hashes
   * Implicit hash for last parameter
   * Variable-length parameter lists
   * Guard clauses
   * Recursive calls to other pattern matches
   * Recursive calls to superclass pattern matches
   * Recursive calls to superclass methods
   * Dispatching to superclass methods when no match is found
   * Reasonable error messages when no match is found

###    Usage

   First, familiarize yourself with Erlang [pattern matching](http://learnyousomeerlang.com/syntax-in-functionspattern-matching).
   This gem may not make much sense if you don't understand how Erlang dispatches functions.

   In the Ruby class file where you want to use pattern matching, require the *functional-ruby* gem:

   ```ruby
   require 'functional'
   ```

   Then include `Functional::PatternMatching` in your class:

   ```ruby
   require 'functional'

   class Foo
     include Functional::PatternMatching

     ...

   end
   ```

   You can then define functions with `defn` instead of the normal *def* statement.
   The syntax for `defn` is:

   ```ruby
   defn(:symbol_name_of_function, zero, or, more, parameters) { |block, arguments|
      code to execute
   }
   ```
   You can then call your new function just like any other:

   ```ruby
   require 'functional/pattern_matching'

   class Foo
     include Functional::PatternMatching

     defn(:hello) {
       puts "Hello, World!"
     }
   end

   foo = Foo.new
   foo.hello => "Hello, World!"
   ```

   Patterns to match against are included in the parameter list:

   ```ruby
   defn(:greet, :male) {
     puts "Hello, sir!"
   }

   defn(:greet, :female) {
     puts "Hello, ma'am!"
   }

   ...

   foo.greet(:male)   => "Hello, sir!"
   foo.greet(:female) => "Hello, ma'am!"
   ```

   If a particular method call can not be matched a *NoMethodError* is thrown with
   a reasonably helpful error message:

   ```ruby
   foo.greet(:unknown) => NoMethodError: no method `greet` matching [:unknown] found for class Foo
   foo.greet           => NoMethodError: no method `greet` matching [] found for class Foo
   ```

   Parameters that are expected to exist but that can take any value are considered
   *unbound* parameters. Unbound parameters are specified by the `_` underscore
   character or `UNBOUND`:

   ```ruby
   defn(:greet, _) do |name|
     "Hello, {name}!"
   end

   defn(:greet, UNBOUND, UNBOUND) do |first, last|
     "Hello, {first} {last}!"
   end

   ...

   foo.greet('Jerry') => "Hello, Jerry!"
   ```

   All unbound parameters will be passed to the block in the order they are specified in the definition:

   ```ruby
   defn(:greet, _, _) do |first, last|
     "Hello, {first} {last}!"
   end

   ...

   foo.greet('Jerry', "D'Antonio") => "Hello, Jerry D'Antonio!"
   ```

   If for some reason you don't care about one or more unbound parameters within
   the block you can use the `_` underscore character in the block parameters list
   as well:

   ```ruby
   defn(:greet, _, _, _) do |first, _, last|
     "Hello, {first} {last}!"
   end

   ...

   foo.greet('Jerry', "I'm not going to tell you my middle name!", "D'Antonio") => "Hello, Jerry D'Antonio!"
   ```

   Hash parameters can match against specific keys and either bound or unbound parameters. This allows for
   function dispatch by hash parameters without having to dig through the hash:

   ```ruby
   defn(:hashable, {foo: :bar}) { |opts|
     :foo_bar
   }
   defn(:hashable, {foo: _}) { |f|
     f
   }

   ...

   foo.hashable({foo: :bar})      => :foo_bar
   foo.hashable({foo: :baz})      => :baz
   ```

   The Ruby idiom of the final parameter being a hash is also supported:

   ```ruby
   defn(:options, _) { |opts|
     opts
   }

   ...

   foo.options(bar: :baz, one: 1, many: 2)
   ```

   As is the Ruby idiom of variable-length argument lists. The constant `ALL` as the last parameter
   will match one or more arguments and pass them to the block as an array:

   ```ruby
   defn(:baz, Integer, ALL) { |int, args|
     [int, args]
   }
   defn(:baz, ALL) { |args|
     args
   }
   ```

   Superclass polymorphism is supported as well. If an object cannot match a method
   signature it will defer to the parent class:

   ```ruby
   class Bar
     def greet
       return 'Hello, World!'
     end
   end

   class Foo < Bar
     include Functional::PatternMatching

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

   ...

   foo.greet('Jerry') => "Hello, Jerry!"
   foo.greet          => "Hello, World!"
   ```

   Guard clauses in Erlang are defined with `when` clauses between the parameter list and the function body.
   In Ruby, guard clauses are defined by chaining a call to `when` onto the the `defn` call and passing
   a block. If the guard clause evaluates to true then the function will match. If the guard evaluates
   to false the function will not match and pattern matching will continue:

   Erlang:

   ```erlang
   old_enough(X) when X >= 16 -> true;
   old_enough(_) -> false.
   ```

   Ruby:

   ```ruby
   defn(:old_enough, _){ |_| true }.when{|x| x >= 16 }
   defn(:old_enough, _){ |_| false }
   ```

#####    Order Matters

   As with Erlang, the order of pattern matches is significant. Patterns will be matched
   *in the order declared* and the first match will be used. If a particular function call
   can be matched by more than one pattern, the *first matched pattern* will be used. It
   is the programmer's responsibility to ensure patterns are declared in the correct order.

#####    Blocks and Procs and Lambdas, oh my!

   When using this gem it is critical to remember that `defn` takes a block and
   that blocks in Ruby have special rules. There are [plenty](https://www.google.com/search?q=ruby+block+proc+lambda)
   of good tutorials on the web explaining [blocks](http://www.robertsosinski.com/2008/12/21/understanding-ruby-blocks-procs-and-lambdas/)
   and [Procs](https://coderwall.com/p/_-_mha) and [lambdas](http://railsguru.org/2010/03/learn-ruby-procs-blocks-lambda/)
   in Ruby. Please read them. Please don't submit a bug report if you use a
   `return` statement within your `defn` and your code blows up with a
   [LocalJumpError](http://ruby-doc.org/core-2.0/LocalJumpError.html).

#####    Examples

   For more examples see the integration tests in *spec/integration_spec.rb*.

    Simple Functions

   This example is based on [Syntax in defnctions: Pattern Matching](http://learnyousomeerlang.com/syntax-in-defnctions) in [Learn You Some Erlang for Great Good!](http://learnyousomeerlang.com/).

   Erlang:

   ```erlang
   greet(male, Name) ->
     io:format("Hello, Mr. ~s!", [Name]);
   greet(female, Name) ->
     io:format("Hello, Mrs. ~s!", [Name]);
   greet(_, Name) ->
     io:format("Hello, ~s!", [Name]).
   ```

   Ruby:

   ```ruby
   require 'functional/pattern_matching'

   class Foo
     include Functional::PatternMatching

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

     defn(:greet, :male, _) { |name|
       "Hello, Mr. {name}!"
     }
     defn(:greet, :female, _) { |name|
       "Hello, Ms. {name}!"
     }
     defn(:greet, _, _) { |_, name|
       "Hello, {name}!"
     }
   end
   ```

#####    Simple Functions with Overloading

   This example is based on [Syntax in defnctions: Pattern Matching](http://learnyousomeerlang.com/syntax-in-defnctions) in [Learn You Some Erlang for Great Good!](http://learnyousomeerlang.com/).

   Erlang:

   ```erlang
   greet(Name) ->
     io:format("Hello, ~s!", [Name]).

   greet(male, Name) ->
     io:format("Hello, Mr. ~s!", [Name]);
   greet(female, Name) ->
     io:format("Hello, Mrs. ~s!", [Name]);
   greet(_, Name) ->
     io:format("Hello, ~s!", [Name]).
   ```

   Ruby:

   ```ruby
   require 'functional/pattern_matching'

   class Foo
     include Functional::PatternMatching

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

     defn(:greet, :male, _) { |name|
       "Hello, Mr. {name}!"
     }
     defn(:greet, :female, _) { |name|
       "Hello, Ms. {name}!"
     }
     defn(:greet, nil, _) { |name|
       "Goodbye, {name}!"
     }
     defn(:greet, _, _) { |_, name|
       "Hello, {name}!"
     }
   end
   ```

    Constructor Overloading

   ```ruby
   require 'functional/pattern_matching'

   class Foo
     include Functional::PatternMatching

     defn(:initialize) { @name = 'baz' }
     defn(:initialize, _) {|name| @name = name.to_s }
   end
   ```

    Matching by Class/Datatype

   ```ruby
   require 'functional/pattern_matching'

   class Foo
     include Functional::PatternMatching

     defn(:concat, Integer, Integer) { |first, second|
       first + second
     }
     defn(:concat, Integer, String) { |first, second|
       "{first} {second}"
     }
     defn(:concat, String, String) { |first, second|
       first + second
     }
     defn(:concat, Integer, _) { |first, second|
       first + second.to_i
     }
   end
   ```

    Matching a Hash Parameter

   ```ruby
   require 'functional/pattern_matching'

   class Foo
     include Functional::PatternMatching

     defn(:hashable, {foo: :bar}) { |opts|
        matches any hash with key :foo and value :bar
       :foo_bar
     }
     defn(:hashable, {foo: _, bar: _}) { |f, b|
        matches any hash with keys :foo and :bar
        passes the values associated with those keys to the block
       [f, b]
     }
     defn(:hashable, {foo: _}) { |f|
        matches any hash with key :foo
        passes the value associated with that key to the block
        must appear AFTER the prior match or it will override that one
       f
     }
     defn(:hashable, {}) { |_|
        matches an empty hash
       :empty
     }
     defn(:hashable, _) { |opts|
        matches any hash (or any other value)
       opts
     }
   end

   ...

   foo.hashable({foo: :bar})      => :foo_bar
   foo.hashable({foo: :baz})      => :baz
   foo.hashable({foo: 1, bar: 2}) => [1, 2]
   foo.hashable({foo: 1, baz: 2}) => 1
   foo.hashable({bar: :baz})      => {bar: :baz}
   foo.hashable({})               => :empty
   ```

    Variable Length Argument Lists with ALL

   ```ruby
   defn(:all, :one, ALL) { |args|
     args
   }
   defn(:all, :one, Integer, ALL) { |int, args|
     [int, args]
   }
   defn(:all, 1, _, ALL) { |var, _, *args|
     [var, args]
   }
   defn(:all, ALL) { |*args|
     args
   }

   ...

   foo.all(:one, 'a', 'bee', :see) => ['a', 'bee', :see]
   foo.all(:one, 1, 'bee', :see)   => [1, 'bee', :see]
   foo.all(1, 'a', 'bee', :see)    => ['a', ['bee', :see]]
   foo.all('a', 'bee', :see)       => ['a', 'bee', :see]
   foo.all()                       => NoMethodError: no method `all` matching [] found for class Foo
   ```

#####    Guard Clauses

   These examples are based on [Syntax in defnctions: Pattern Matching](http://learnyousomeerlang.com/syntax-in-defnctions)
   in [Learn You Some Erlang for Great Good!](http://learnyousomeerlang.com/).

   Erlang:

   ```erlang
   old_enough(X) when X >= 16 -> true;
   old_enough(_) -> false.

   right_age(X) when X >= 16, X =< 104 ->
     true;
   right_age(_) ->
     false.

   wrong_age(X) when X < 16; X > 104 ->
     true;
   wrong_age(_) ->
     false.
   ```

   ```ruby
   defn(:old_enough, _){ |_| true }.when{|x| x >= 16 }
   defn(:old_enough, _){ |_| false }

   defn(:right_age, _) { |_|
     true
   }.when{|x| x >= 16 && x <= 104 }

   defn(:right_age, _) { |_|
     false
   }

   defn(:wrong_age, _) { |_|
     false
   }.when{|x| x < 16 || x > 104 }

   defn(:wrong_age, _) { |_|
     true
   }
   ```

###    Inspiration

   Pattern matching has its roots in logic programming languages such as
   [Prolog](http://en.wikipedia.org/wiki/Prolog). Pattern matching is a core
   feature of the [Erlang](http://www.erlang.org/) programming language. A few
   helpful resources are:

   * Erlang [modules](http://erlang.org/doc/reference_manual/modules.html)
   * Erlang [pattern matching](http://erlang.org/doc/reference_manual/patterns.html)


================================================
FILE: doc/protocol.md
================================================
###    Rationale

   Traditional object orientation implements polymorphism inheritance. The *Is-A*
   relationship indicates that one object "is a" instance of another object.
   Implicit in this relationship, however, is the concept of [type](http://en.wikipedia.org/wiki/Data_type).
   Every Ruby object has a *type*, and that type is the name of its `Class` or
   `Module`. The Ruby runtime provides a number of reflective methods that allow
   objects to be interrogated for type information. The principal of thses is the
   `is_a?` (alias `kind_of`) method defined in class `Object`.

   Unlike many traditional object oriented languages, Ruby is a [dynamically typed](http://en.wikipedia.org/wiki/Dynamic_typingDYNAMIC)
   language. Types exist but the runtime is free to cast one type into another
   at any time. Moreover, Ruby is a [duck typed](http://en.wikipedia.org/wiki/Duck_typing).
   If an object "walks like a duck and quacks like a duck then it must be a duck."
   When a method needs called on an object Ruby does not check the type of the object,
   it simply checks to see if the requested function exists with the proper
   [arity](http://en.wikipedia.org/wiki/Arity) and, if it does, dispatches the call.
   The duck type analogue to `is_a?` is `respond_to?`. Thus an object can be interrogated
   for its behavior rather than its type.

   Although Ruby offers several methods for reflecting on the behavior of a module/class/object,
   such as `method`, `instance_methods`, `const_defined?`, the aforementioned `respond_to?`,
   and others, Ruby lacks a convenient way to group collections of methods in any way that
   does not involve type. Both modules and classes provide mechanisms for combining
   methods into cohesive abstractions, but they both imply type. This is anathema to Ruby's
   dynamism and duck typing. What Ruby needs is a way to collect a group of method names
   and signatures into a cohesive collection that embraces duck typing and dynamic dispatch.
   This is what protocols do.

###    Specifying

   A "protocol" is a loose collection of method, attribute, and constant names with optional
   arity values. The protocol definition does very little on its own. The power of protocols
   is that they provide a way for modules, classes, and objects to be interrogated with
   respect to common behavior, not common type. At the core a protocol is nothing more
   than a collection of `respond_to?` method calls that ask the question "Does this thing
   *behave* like this other thing."

   Protocols are specified with the `Functional::SpecifyProtocol` method. It takes one parameter,
   the name of the protocol, and a block which contains the protocol specification. This registers
   the protocol specification and makes it available for use later when interrogating ojects
   for their behavior.

#####    Defining Attributes, Methods, and Constants

   A single protocol specification can include definition for attributes, methods,
   and constants. Methods and attributes can be defined as class/module methods or
   as instance methods. Within the a protocol specification each item must include
   the symbolic name of the item being defined.

   ```ruby
   Functional::SpecifyProtocol(:KitchenSink) do
     instance_method     :instance_method
     class_method        :class_method
     attr_accessor       :attr_accessor
     attr_reader         :attr_reader
     attr_writer         :attr_writer
     class_attr_accessor :class_attr_accessor
     class_attr_reader   :class_attr_reader
     class_attr_writer   :class_attr_writer
     constant            :CONSTANT
   end
   ```

   Definitions for accessors are expanded at specification into the apprporiate
   method(s). Which means that this:

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

   is the same as:

   ```ruby
   Functional::SpecifyProtocol(:Name) do
     instance_method :first
     instance_method :first=
     instance_method :middle
     instance_method :middle=
     instance_method :last
     instance_method :last=
     instance_method :suffix
     instance_method :suffix=
   end
   ```

   Protocols only care about the methods themselves, not how they were declared.

###    Arity

   In addition to defining *which* methods exist, the required method arity can
   indicated. Arity is optional. When no arity is given any arity will be expected.
   The arity rules follow those defined for the `arity` method of Ruby's
   [Method class](http://www.ruby-doc.org/core-2.1.2/Method.htmlmethod-i-arity):

   * Methods with a fixed number of arguments have a non-negative arity
   * Methods with optional arguments have an arity `-n - 1`, where n is the number of required arguments
   * Methods with a variable number of arguments have an arity of `-1`

   ```ruby
   Functional::SpecifyProtocol(:Foo) do
     instance_method :any_args
     instance_method :no_args, 0
     instance_method :three_args, 3
     instance_method :optional_args, -2
     instance_method :variable_args, -1
   end

   class Bar

     def any_args(a, b, c=1, d=2, *args)
     end

     def no_args
     end

     def three_args(a, b, c)
     end

     def optional_args(a, b=1, c=2)
     end

     def variable_args(*args)
     end
   end
   ```

###    Reflection

   Once a protocol has been defined, any class, method, or object may be interrogated
   for adherence to one or more protocol specifications. The methods of the
   `Functional::Protocol` classes provide this capability. The `Satisfy?` method
   takes a module/class/object as the first parameter and one or more protocol names
   as the second and subsequent parameters. It returns a boolean value indicating
   whether the given object satisfies the protocol requirements:

   ```ruby
   Functional::SpecifyProtocol(:Queue) do
     instance_method :push, 1
     instance_method :pop, 0
     instance_method :length, 0
   end

   Functional::SpecifyProtocol(:List) do
     instance_method :[]=, 2
     instance_method :[], 1
     instance_method :each, 0
     instance_method :length, 0
   end

   Functional::Protocol::Satisfy?(Queue, :Queue)        => true
   Functional::Protocol::Satisfy?(Queue, :List)         => false

   list = [1, 2, 3]
   Functional::Protocol::Satisfy?(Array, :List, :Queue) => true
   Functional::Protocol::Satisfy?(list, :List, :Queue)  => true

   Functional::Protocol::Satisfy?(Hash, :Queue)         => false

   Functional::Protocol::Satisfy?('foo bar baz', :List) => false
   ```

   The `Satisfy!` method performs the exact same check but instead raises an exception
   when the protocol is not satisfied:

   ```
   2.1.2 :021 > Functional::Protocol::Satisfy!(Queue, :List)
   Functional::ProtocolError: Value (Class) 'Thread::Queue' does not behave as all of: :List.
   	from /Projects/functional-ruby/lib/functional/protocol.rb:67:in `error'
   	from /Projects/functional-ruby/lib/functional/protocol.rb:36:in `Satisfy!'
   	from (irb):21
     ...
   ```
   The `Functional::Protocol` module can be included within other classes
   to eliminate the namespace requirement when calling:

   ```ruby
   class MessageFormatter
     include Functional::Protocol

     def format(message)
       if Satisfy?(message, :Internal)
         format_internal_message(message)
       elsif Satisfy?(message, :Error)
         format_error_message(message)
       else
         format_generic_message(message)
       end
     end

     private

     def format_internal_message(message)
        format the message...
     end

     def format_error_message(message)
        format the message...
     end

     def format_generic_message(message)
        format the message...
     end
   ```

###   Inspiration

   Protocols and similar functionality exist in several other programming languages.
   A few languages that provided inspiration for this inplementation are:

   * Clojure [protocol](http://clojure.org/protocols)
   * Erlang [behaviours](http://www.erlang.org/doc/design_principles/des_princ.htmlid60128)
   * Objective-C [protocol](https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/ProgrammingWithObjectiveC/WorkingwithProtocols/WorkingwithProtocols.html)
     (and the corresponding Swift [protocol](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Protocols.html))


================================================
FILE: doc/record.md
================================================
###    Declaration

   A `Record` class is declared in a manner identical to that used with Ruby's `Struct`.
   The class method `new` is called with a list of one or more field names (symbols).
   A new class will then be dynamically generated along with the necessary reader
   attributes, one for each field. The newly created class will be anonymous and
   will mixin `Functional::AbstractStruct`. The best practice is to assign the newly
   created record class to a constant:

   ```ruby
   Customer = Functional::Record.new(:name, :address) => Customer
   ```

   Alternatively, the name of the record class, as a string, can be given as the
   first parameter. In this case the new record class will be created as a constant
   within the `Record` module:

   ```ruby
   Functional::Record.new("Customer", :name, :address) => Functional::Record::Customer
   ```

###    Type Specification

   Unlike a Ruby `Struct`, a `Record` may be declared with a type/protocol
   specification. In this case, all data members are checked against the
   specification whenever a new record is created. Declaring a `Record` with a
   type specification is similar to declaring a normal `Record`, except that
   the field list is given as a hash with field names as the keys and a class or
   protocol as the values.

   ```ruby
   Functional::SpecifyProtocol(:Name) do
     attr_reader :first
     attr_reader :middle
     attr_reader :last
   end

   TypedCustomer = Functional::Record.new(name: :Name, address: String) => TypedCustomer

   Functional::Record.new("TypedCustomer", name: :Name, address: String) => Functional::Record::TypedCustomer
   ```

###    Construction

   Construction of a new object from a record is slightly different than for a Ruby `Struct`.
   The constructor for a struct class may take zero or more field values and will use those
   values to popuate the fields. The values passed to the constructor are assumed to be in
   the same order as the fields were defined. This works for a struct because it is
   mutable--the field values may be changed after instanciation. Therefore it is not
   necessary to provide all values to a stuct at creation. This is not the case for a
   record. A record is immutable. The values for all its fields must be set at instanciation
   because they cannot be changed later. When creating a new record object the constructor
   will accept a collection of field/value pairs in hash syntax and will create the new
   record with the given values:

   ```ruby
   Customer.new(name: 'Dave', address: '123 Main')
    => <record Customer :name=>"Dave", :address=>"123 Main">

   Functional::Record::Customer.new(name: 'Dave', address: '123 Main')
    => <record Functional::Record::Customer :name=>"Dave", :address=>"123 Main">
   ```

   When a record is defined with a type/protocol specification, the values of
   all non-nil data members are checked against the specification. Any data
   value that is not of the given type or does not satisfy the given protocol
   will cause an exception to be raised:

   ```ruby
   class Name
     attr_reader :first, :middle, :last
     def initialize(first, middle, last)
       @first = first
       @middle = middle
       @last = last
     end
   end

   name = Name.new('Douglas', nil, 'Adams') => <Name:0x007fc8b951a278 ...
   TypedCustomer.new(name: name, address: '123 Main') => <record TypedCustomer :name=><Name:0x007f914cce05b0 ...

   TypedCustomer.new(name: 'Douglas Adams', address: '123 Main') => ArgumentError: 'name' must stasify the protocol :Name
   TypedCustomer.new(name: name, address: 42) => ArgumentError: 'address' must be of type String
   ```

###    Default Values

   By default, all record fields are set to `nil` at instanciation unless explicity set
   via the constructor. It is possible to specify default values other than `nil` for
   zero or more of the fields when a new record class is created. The `new` method of
   `Record` accepts a block which can be used to declare new default values:

   ```ruby
   Address = Functional::Record.new(:street_line_1, :street_line_2,
                                    :city, :state, :postal_code, :country) do
     default :state, 'Ohio'
     default :country, 'USA'
   end
    => Address
   ```

   When a new object is created from a record class with explicit default values, those
   values will be used for the appropriate fields when no other value is given at
   construction:

   ```ruby
   Address.new(street_line_1: '2401 Ontario St',
               city: 'Cleveland', postal_code: 44115)
    => <record Address :street_line_1=>"2401 Ontario St", :street_line_2=>nil, :city=>"Cleveland", :state=>"Ohio", :postal_code=>44115, :country=>"USA">
   ```

   Of course, if a value for a field is given at construction that value will be used instead
   of the custom default:

   ```ruby
   Address.new(street_line_1: '1060 W Addison St',
               city: 'Chicago', state: 'Illinois', postal_code: 60613)
    => <record Address :street_line_1=>"1060 W Addison St", :street_line_2=>nil, :city=>"Chicago", :state=>"Illinois", :postal_code=>60613, :country=>"USA">
   ```

###    Mandatory Fields

   By default, all record fields are optional. It is perfectly legal for a record
   object to exist with all its fields set to `nil`. During declaration of a new record
   class the block passed to `Record.new` can also be used to indicate which fields
   are mandatory. When a new object is created from a record with mandatory fields
   an exception will be thrown if any of those fields are nil:

   ```ruby
   Name = Functional::Record.new(:first, :middle, :last, :suffix) do
     mandatory :first, :last
   end
    => Name

   Name.new(first: 'Joe', last: 'Armstrong')
    => <record Name :first=>"Joe", :middle=>nil, :last=>"Armstrong", :suffix=>nil>

   Name.new(first: 'Matz') => ArgumentError: mandatory fields must not be nil
   ```

   Of course, declarations for default values and mandatory fields may be used
   together:

   ```ruby
   Person = Functional::Record.new(:first_name, :middle_name, :last_name,
                                   :street_line_1, :street_line_2,
                                   :city, :state, :postal_code, :country) do
     mandatory :first_name, :last_name
     mandatory :country
     default :state, 'Ohio'
     default :country, 'USA'
   end
    => Person
   ```

###    Default Value Memoization

   Note that the block provided to `Record.new` is processed once and only once
   when the new record class is declared. Thereafter the results are memoized
   and copied (via `clone`, unless uncloneable) each time a new record object
   is created. Default values should be simple types like `String`, `Fixnum`,
   and `Boolean`. If complex operations need performed when setting default
   values the a `Class` should be used instead of a `Record`.

#####    Why Declaration Differs from Ruby's Struct

   Those familiar with Ruby's `Struct` class will notice one important
   difference when declaring a `Record`: the block passes to `new` cannot be
   used to define additional methods. When declaring a new class created from a
   Ruby `Struct` the block can perform any additional class definition that
   could be done had the class be defined normally. The excellent
   [Values](https://github.com/tcrayford/Values) supports this same behavior.
   `Record` does not allow additional class definitions during declaration for
   one simple reason: doing so violates two very important tenets of functional
   programming. Specifically, immutability and the separation of data from
   operations.

   `Record` exists for the purpose of creating immutable objects. If additional
   instance methods were to be defined on a record class it would be possible
   to violate immutability. Not only could additional, mutable state be added
   to the class, but the existing immutable attributes could be overridden by
   mutable methods. The security of providing an immutable object would be
   completely shattered, thus defeating the original purpose of the record
   class. Of course it would be possible to allow this feature and trust the
   programmer to not violate the intended immutability of class, but opening
   `Record` to the *possibility* of immutability violation is unnecessary and
   unwise.

   More important than the potential for immutability violations is the fact
   the adding additional methods to a record violates the principal of
   separating data from operations on that data. This is one of the core ideas
   in functional programming. Data is defined in pure structures that contain
   no behavior and operations on that data are provided by polymorphic
   functions. This may seem counterintuitive to object oriented programmers,
   but that is the nature of functional programming. Adding behavior to a
   record, even when that behavior does not violate immutability, is still
   anathema to functional programming, and it is why records in languages like
   Erlang and Clojure do not have functions defined within them.

   Should additional methods need defined on a `Record` class, the appropriate
   practice is to declare the record class then declare another class which
   extends the record. The record class remains pure data and the subclass
   contains additional operations on that data.

   ```ruby
   NameRecord = Functional::Record.new(:first, :middle, :last, :suffix) do
     mandatory :first, :last
   end

   class Name < NameRecord
     def full_name
       "{first} {last}"
     end

     def formal_name
       name = [first, middle, last].select{|s| ! s.to_s.empty?}.join(' ')
       suffix.to_s.empty? ? name : name + ", {suffix}"
     end
   end

   jerry = Name.new(first: 'Jerry', last: "D'Antonio")
   ted   = Name.new(first: 'Ted', middle: 'Theodore', last: 'Logan', suffix: 'Esq.')

   jerry.formal_name => "Jerry D'Antonio"
   ted.formal_name   => "Ted Theodore Logan, Esq."
   ```

###    Inspiration

   Neither struct nor records are new to computing. Both have been around for a very
   long time. Mutable structs can be found in many languages including
   [Ruby](http://www.ruby-doc.org/core-2.1.2/Struct.html),
   [Go](http://golang.org/ref/specStruct_types),
   [C](http://en.wikipedia.org/wiki/Struct_(C_programming_language)),
   and [C](http://msdn.microsoft.com/en-us/library/ah19swz4.aspx),
   just to name a few. Immutable records exist primarily in functional languages
   like [Haskell](http://en.wikibooks.org/wiki/Haskell/More_on_datatypesNamed_Fields_.28Record_Syntax.29),
   Clojure, and Erlang. The inspiration for declaring records with a type
   specification is taken from [PureScript](http://www.purescript.org/), a
   compile-to-JavaScript language inspired by Haskell.

   * [Ruby Struct](http://www.ruby-doc.org/core-2.1.2/Struct.html)
   * [Clojure Datatypes](http://clojure.org/datatypes)
   * [Clojure *defrecord* macro](http://clojure.github.io/clojure/clojure.core-api.htmlclojure.core/defrecord)
   * [Erlang Records (Reference)](http://www.erlang.org/doc/reference_manual/records.html)
   * [Erlang Records (Examples)](http://www.erlang.org/doc/programming_examples/records.html)
   * [PureScript Records](http://docs.purescript.org/en/latest/types.htmlrecords)


================================================
FILE: functional_ruby.gemspec
================================================
$LOAD_PATH << File.expand_path('../lib', __FILE__)

require 'functional/version'

Gem::Specification.new do |s|
  s.name        = 'functional-ruby'
  s.version     = Functional::VERSION
  s.platform    = Gem::Platform::RUBY
  s.author      = "Jerry D'Antonio"
  s.email       = 'jerry.dantonio@gmail.com'
  s.homepage    = 'https://github.com/jdantonio/functional-ruby/'
  s.summary     = 'Erlang, Clojure, Haskell, and Functional Java inspired functional programming tools for Ruby.'
  s.license     = 'MIT'
  s.date        = Time.now.strftime('%Y-%m-%d')

  s.description = <<-EOF
    A gem for adding functional programming tools to Ruby. Inspired by Erlang, Clojure, Haskell, and Functional Java.
  EOF

  s.files             = Dir['README*', 'LICENSE*', 'CHANGELOG*']
  s.files            += Dir['{lib}/**/*']
  s.test_files        = Dir['{spec}/**/*']
  s.extra_rdoc_files  = Dir['README*', 'LICENSE*', 'CHANGELOG*']
  s.extra_rdoc_files += Dir['{doc}/**/*.{txt,md}']
  s.require_paths     = ['lib']

  s.required_ruby_version = '>= 2.0.0'
end


================================================
FILE: lib/functional/abstract_struct.rb
================================================
require 'functional/protocol'
require 'functional/synchronization'

Functional::SpecifyProtocol(:Struct) do
  instance_method :fields
  instance_method :values
  instance_method :length
  instance_method :each
  instance_method :each_pair
end

module Functional

  # An abstract base class for immutable struct classes.
  # @!visibility private
  module AbstractStruct

    # @return [Array] the values of all record fields in order, frozen
    attr_reader :values

    # Yields the value of each record field in order.
    # If no block is given an enumerator is returned.
    #
    # @yieldparam [Object] value the value of the given field
    #
    # @return [Enumerable] when no block is given
    def each
      return enum_for(:each) unless block_given?
      fields.each do |field|
        yield(self.send(field))
      end
    end

    # Yields the name and value of each record field in order.
    # If no block is given an enumerator is returned.
    #
    # @yieldparam [Symbol] field the record field for the current iteration
    # @yieldparam [Object] value the value of the current field
    #
    # @return [Enumerable] when no block is given
    def each_pair
      return enum_for(:each_pair) unless block_given?
      fields.each do |field|
        yield(field, self.send(field))
      end
    end

    # Equality--Returns `true` if `other` has the same record subclass and has equal
    # field values (according to `Object#==`).
    #
    # @param [Object] other the other record to compare for equality
    # @return [Boolean] true when equal else false
    def eql?(other)
      self.class == other.class && self.to_h == other.to_h
    end
    alias_method :==, :eql?

    # @!macro [attach] inspect_method
    #
    #   Describe the contents of this struct in a string. Will include the name of the
    #   record class, all fields, and all values.
    #
    #   @return [String] the class and contents of this record
    def inspect
      state = to_h.to_s.gsub(/^{/, '').gsub(/}$/, '')
      "#<#{self.class.datatype} #{self.class} #{state}>"
    end
    alias_method :to_s, :inspect

    # Returns the number of record fields.
    #
    # @return [Fixnum] the number of record fields
    def length
      fields.length
    end
    alias_method :size, :length

    # A frozen array of all record fields.
    #
    # @return [Array] all record fields in order, frozen
    def fields
      self.class.fields
    end

    # Returns a Hash containing the names and values for the record’s fields.
    #
    # @return [Hash] collection of all fields and their associated values
    def to_h
      @data
    end

    protected

    # Set the internal data hash to a copy of the given hash and freeze it.
    # @param [Hash] data the data hash
    #
    # @!visibility private
    def set_data_hash(data)
      @data = data.dup.freeze
    end

    # Set the internal values array to a copy of the given array and freeze it.
    # @param [Array] values the values array
    #
    # @!visibility private
    def set_values_array(values)
      @values = values.dup.freeze
    end

    # Define a new struct class and, if necessary, register it with
    # the calling class/module. Will also set the datatype and fields
    # class attributes on the new struct class.
    #
    # @param [Module] parent the class/module that is defining the new struct
    # @param [Symbol] datatype the datatype value for the new struct class
    # @param [Array] fields the list of symbolic names for all data fields
    # @return [Functional::AbstractStruct, Array] the new class and the
    #   (possibly) updated fields array
    #
    # @!visibility private
    def self.define_class(parent, datatype, fields)
      struct = Class.new(Functional::Synchronization::Object){ include AbstractStruct }
      if fields.first.is_a? String
        parent.const_set(fields.first, struct)
        fields = fields[1, fields.length-1]
      end
      fields = fields.collect{|field| field.to_sym }.freeze
      struct.send(:datatype=, datatype.to_sym)
      struct.send(:fields=, fields)
      [struct, fields]
    end

    private

    def self.included(base)
      base.extend(ClassMethods)
      super(base)
    end

    # Class methods added to a class that includes {Functional::PatternMatching}
    #
    # @!visibility private
    module ClassMethods

      # A frozen Array of all record fields in order
      attr_reader :fields

      # A symbol describing the object's datatype
      attr_reader :datatype

      private

      # A frozen Array of all record fields in order
      attr_writer :fields

      # A symbol describing the object's datatype
      attr_writer :datatype

      fields = [].freeze
      datatype = :struct
    end
  end
end


================================================
FILE: lib/functional/delay.rb
================================================
require 'functional/synchronization'

module Functional

  # Lazy evaluation of a block yielding an immutable result. Useful for
  # expensive operations that may never be needed.
  #
  # When a `Delay` is created its state is set to `pending`. The value and
  # reason are both `nil`. The first time the `#value` method is called the
  # enclosed opration will be run and the calling thread will block. Other
  # threads attempting to call `#value` will block as well. Once the operation
  # is complete the *value* will be set to the result of the operation or the
  # *reason* will be set to the raised exception, as appropriate. All threads
  # blocked on `#value` will return. Subsequent calls to `#value` will
  # immediately return the cached value. The operation will only be run once.
  # This means that any side effects created by the operation will only happen
  # once as well.
  #
  # @!macro [new] thread_safe_immutable_object
  #
  #    @note This is a write-once, read-many, thread safe object that can be
  #      used in concurrent systems. Thread safety guarantees *cannot* be made
  #      about objects contained *within* this object, however. Ruby variables
  #      are mutable references to mutable objects. This cannot be changed. The
  #      best practice it to only encapsulate immutable, frozen, or thread safe
  #      objects. Ultimately, thread safety is the responsibility of the
  #      programmer.
  #
  # @see http://clojuredocs.org/clojure_core/clojure.core/delay Clojure delay
  class Delay < Synchronization::Object

    # Create a new `Delay` in the `:pending` state.
    #
    # @yield the delayed operation to perform
    #
    # @raise [ArgumentError] if no block is given
    def initialize(&block)
      raise ArgumentError.new('no block given') unless block_given?
      super
      synchronize do
        @state = :pending
        @task  = block
      end
    end

    # Current state of block processing.
    #
    # @return [Symbol] the current state of block processing
    def state
      synchronize{ @state }
    end

    # The exception raised when processing the block. Returns `nil` if the
    # operation is still `:pending` or has been `:fulfilled`.
    #
    # @return [StandardError] the exception raised when processing the block
    #   else nil.
    def reason
      synchronize{ @reason }
    end

    # Return the (possibly memoized) value of the delayed operation.
    #
    # If the state is `:pending` then the calling thread will block while the
    # operation is performed. All other threads simultaneously calling `#value`
    # will block as well. Once the operation is complete (either `:fulfilled` or
    # `:rejected`) all waiting threads will unblock and the new value will be
    # returned.
    #
    # If the state is not `:pending` when `#value` is called the (possibly
    # memoized) value will be returned without blocking and without performing
    # the operation again.
    #
    # @return [Object] the (possibly memoized) result of the block operation
    def value
      synchronize{ execute_task_once }
    end

    # Has the delay been fulfilled?
    # @return [Boolean]
    def fulfilled?
      synchronize{ @state == :fulfilled }
    end
    alias_method :value?, :fulfilled?

    # Has the delay been rejected?
    # @return [Boolean]
    def rejected?
      synchronize{ @state == :rejected }
    end
    alias_method :reason?, :rejected?

    # Is delay completion still pending?
    # @return [Boolean]
    def pending?
      synchronize{ @state == :pending }
    end

    protected

    # @!visibility private
    #
    # Execute the enclosed task then cache and return the result if the current
    # state is pending. Otherwise, return the cached result.
    #
    # @return [Object] the result of the block operation
    def execute_task_once
      if @state == :pending
        begin
          @value = @task.call
          @state = :fulfilled
        rescue => ex
          @reason = ex
          @state  = :rejected
        end
      end
      @value
    end
  end
end


================================================
FILE: lib/functional/either.rb
================================================
require 'functional/abstract_struct'
require 'functional/protocol'
require 'functional/synchronization'

Functional::SpecifyProtocol(:Either) do
  instance_method :left, 0
  instance_method :left?, 0
  instance_method :right, 0
  instance_method :right?, 0
end

module Functional

  # The `Either` type represents a value of one of two possible types (a
  # disjoint union). It is an immutable structure that contains one and only one
  # value. That value can be stored in one of two virtual position, `left` or
  # `right`. The position provides context for the encapsulated data.
  #
  # One of the main uses of `Either` is as a return value that can indicate
  # either success or failure. Object oriented programs generally report errors
  # through either state or exception handling, neither of which work well in
  # functional programming. In the former case, a method is called on an object
  # and when an error occurs the state of the object is updated to reflect the
  # error. This does not translate well to functional programming because they
  # eschew state and mutable objects. In the latter, an exception handling block
  # provides branching logic when an exception is thrown. This does not
  # translate well to functional programming because it eschews side effects
  # like structured exception handling (and structured exception handling tends
  # to be very expensive). `Either` provides a powerful and easy-to-use
  # alternative.
  #
  # A function that may generate an error can choose to return an immutable
  # `Either` object in which the position of the value (left or right) indicates
  # the nature of the data. By convention, a `left` value indicates an error and
  # a `right` value indicates success. This leaves the caller with no ambiguity
  # regarding success or failure, requires no persistent state, and does not
  # require expensive exception handling facilities.
  #
  # `Either` provides several aliases and convenience functions to facilitate
  # these failure/success conventions. The `left` and `right` functions,
  # including their derivatives, are mirrored by `reason` and `value`. Failure
  # is indicated by the presence of a `reason` and success is indicated by the
  # presence of a `value`. When an operation has failed the either is in a
  # `rejected` state, and when an operation has successed the either is in a
  # `fulfilled` state. A common convention is to use a Ruby `Exception` as the
  # `reason`. The factory method `error` facilitates this. The semantics and
  # conventions of `reason`, `value`, and their derivatives follow the
  # conventions of the Concurrent Ruby gem.
  #
  # The `left`/`right` and `reason`/`value` methods are not mutually exclusive.
  # They can be commingled and still result in functionally correct code. This
  # practice should be avoided, however. Consistent use of either `left`/`right`
  # or `reason`/`value` against each `Either` instance will result in more
  # expressive, intent-revealing code.
  #
  # @example
  #
  #   require 'uri'
  #
  #   def web_host(url)
  #     uri = URI(url)
  #     if uri.scheme != 'http'
  #       Functional::Either.left('Invalid HTTP URL')
  #     else
  #       Functional::Either.right(uri.host)
  #     end
  #   end
  #
  #   good = web_host('http://www.concurrent-ruby.com')
  #   good.right? #=> true
  #   good.right  #=> "www.concurrent-ruby"
  #   good.left #=> nil
  #
  #   good = web_host('bogus')
  #   good.right? #=> false
  #   good.right  #=> nil
  #   good.left #=> "Invalid HTTP URL"
  #
  # @see http://functionaljava.googlecode.com/svn/artifacts/3.0/javadoc/fj/data/Either.html Functional Java
  # @see https://hackage.haskell.org/package/base-4.2.0.1/docs/Data-Either.html Haskell Data.Either
  # @see http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/Obligation.html Concurrent Ruby
  #
  # @!macro thread_safe_immutable_object
  class Either < Synchronization::Object
    include AbstractStruct

    self.datatype = :either
    self.fields = [:left, :right].freeze

    # @!visibility private
    NO_VALUE = Object.new.freeze

    private_class_method :new

    class << self

      # Construct a left value of either.
      #
      # @param [Object] value The value underlying the either.
      # @return [Either] A new either with the given left value.
      def left(value)
        new(value, true).freeze
      end
      alias_method :reason, :left

      # Construct a right value of either.
      #
      # @param [Object] value The value underlying the either.
      # @return [Either] A new either with the given right value.
      def right(value)
        new(value, false).freeze
      end
      alias_method :value, :right

      # Create an `Either` with the left value set to an `Exception` object
      # complete with message and backtrace. This is a convenience method for
      # supporting the reason/value convention with the reason always being
      # an `Exception` object. When no exception class is given `StandardError`
      # will be used. When no message is given the default message for the
      # given error class will be used.
      #
      # @example
      #
      #   either = Functional::Either.error("You're a bad monkey, Mojo Jojo")
      #   either.fulfilled? #=> false
      #   either.rejected?  #=> true
      #   either.value      #=> nil
      #   either.reason     #=> #<StandardError: You're a bad monkey, Mojo Jojo>
      #
      # @param [String] message The message for the new error object.
      # @param [Exception] clazz The class for the new error object.
      # @return [Either] A new either with an error object as the left value.
      def error(message = nil, clazz = StandardError)
        ex = clazz.new(message)
        ex.set_backtrace(caller)
        left(ex)
      end
    end

    # Projects this either as a left.
    #
    # @return [Object] The left value or `nil` when `right`.
    def left
      left? ? to_h[:left] : nil
    end
    alias_method :reason, :left

    # Projects this either as a right.
    #
    # @return [Object] The right value or `nil` when `left`.
    def right
      right? ? to_h[:right] : nil
    end
    alias_method :value, :right

    # Returns true if this either is a left, false otherwise.
    #
    # @return [Boolean] `true` if this either is a left, `false` otherwise.
    def left?
      @is_left
    end
    alias_method :reason?, :left?
    alias_method :rejected?, :left?

    # Returns true if this either is a right, false otherwise.
    #
    # @return [Boolean] `true` if this either is a right, `false` otherwise.
    def right?
      ! left?
    end
    alias_method :value?, :right?
    alias_method :fulfilled?, :right?

    # If this is a left, then return the left value in right, or vice versa.
    #
    # @return [Either] The value of this either swapped to the opposing side.
    def swap
      if left?
        self.class.send(:new, left, false)
      else
        self.class.send(:new, right, true)
      end
    end

    # The catamorphism for either. Folds over this either breaking into left or right.
    #
    # @param [Proc] lproc The function to call if this is left.
    # @param [Proc] rproc The function to call if this is right.
    # @return [Object] The reduced value.
    def either(lproc, rproc)
      left? ? lproc.call(left) : rproc.call(right)
    end

    # If the condition satisfies, return the given A in left, otherwise, return the given B in right.
    #
    # @param [Object] lvalue The left value to use if the condition satisfies.
    # @param [Object] rvalue The right value to use if the condition does not satisfy.
    # @param [Boolean] condition The condition to test (when no block given).
    # @yield The condition to test (when no condition given).
    #
    # @return [Either] A constructed either based on the given condition.
    #
    # @raise [ArgumentError] When both a condition and a block are given.
    def self.iff(lvalue, rvalue, condition = NO_VALUE)
      raise ArgumentError.new('requires either a condition or a block, not both') if condition != NO_VALUE && block_given?
      condition = block_given? ? yield : !! condition
      condition ? left(lvalue) : right(rvalue)
    end

    private

    # Create a new Either wil the given value and disposition.
    #
    # @param [Object] value the value of this either
    # @param [Boolean] is_left is this a left either or right?
    #
    # @!visibility private
    def initialize(value, is_left)
      super
      @is_left = is_left
      hsh = is_left ? {left: value, right: nil} : {left: nil, right: value}
      set_data_hash(hsh)
      set_values_array(hsh.values)
      ensure_ivar_visibility!
    end
  end
end


================================================
FILE: lib/functional/final_struct.rb
================================================
require 'functional/final_var'
require 'functional/synchronization'

module Functional

  # A variation on Ruby's `OpenStruct` in which all fields are "final" (meaning
  # that new fields can be arbitrarily added to a `FinalStruct` object but once
  # set each field becomes immutable). Additionally, predicate methods exist for
  # all fields and these predicates indicate if the field has been set.
  #
  # There are two ways to initialize a `FinalStruct`: with zero arguments or
  # with a `Hash` (or any other object that implements a `to_h` method). The
  # only difference in behavior is that a `FinalStruct` initialized with a
  # hash will pre-define and pre-populate attributes named for the hash keys
  # and with values corresponding to the hash values.
  #
  # @example Instanciation With No Fields
  #   bucket = Functional::FinalStruct.new
  #
  #   bucket.foo      #=> nil
  #   bucket.foo?     #=> false
  #
  #   bucket.foo = 42 #=> 42
  #   bucket.foo      #=> 42
  #   bucket.foo?     #=> true
  #
  #   bucket.foo = 42 #=> Functional::FinalityError: final accessor 'bar' has already been set
  #
  # @example Instanciation With a Hash
  #   name = Functional::FinalStruct.new(first: 'Douglas', last: 'Adams')
  #
  #   name.first           #=> 'Douglas'
  #   name.last            #=> 'Adams'
  #   name.first?          #=> true
  #   name.last?           #=> true
  #
  #   name.middle #=> nil
  #   name.middle?         #=> false
  #   name.middle = 'Noel' #=> 'Noel'
  #   name.middle?         #=> true
  #
  #   name.first = 'Sam'   #=> Functional::FinalityError: final accessor 'first' has already been set
  #
  # @see http://www.ruby-doc.org/stdlib-2.1.2/libdoc/ostruct/rdoc/OpenStruct.html
  # @see http://en.wikipedia.org/wiki/Final_(Java) Java `final` keyword
  #
  # @!macro thread_safe_final_object
  class FinalStruct < Synchronization::Object

    # Creates a new `FinalStruct` object. By default, the resulting `FinalStruct`
    # object will have no attributes. The optional hash, if given, will generate
    # attributes and values (can be a `Hash` or any object with a `to_h` method).
    #
    # @param [Hash] attributes the field/value pairs to set on creation
    def initialize(attributes = {})
      raise ArgumentError.new('attributes must be given as a hash or not at all') unless attributes.respond_to?(:to_h)
      super
      synchronize do
        @attribute_hash = {}
        attributes.to_h.each_pair do |field, value|
          ns_set_attribute(field, value)
        end
      end
    end

    # @!macro [attach] final_struct_get_method
    #
    #   Get the value of the given field.
    #
    #   @param [Symbol] field the field to retrieve the value for
    #   @return [Object] the value of the field is set else nil
    def get(field)
      synchronize { ns_get_attribute(field) }
    end
    alias_method :[], :get

    # @!macro [attach] final_struct_set_method
    #
    #   Set the value of the give field to the given value.
    #
    #   It is a logical error to attempt to set a `final` field more than once, as this
    #   violates the concept of finality. Calling the method a second or subsequent time
    #   for a given field will result in an exception being raised.
    #
    #   @param [Symbol] field the field to set the value for
    #   @param [Object] value the value to set the field to
    #   @return [Object] the final value of the given field
    #
    # @raise [Functional::FinalityError] if the given field has already been set
    def set(field, value)
      synchronize do
        if ns_attribute_has_been_set?(field)
          raise FinalityError.new("final accessor '#{field}' has already been set")
        else
          ns_set_attribute(field, value)
        end
      end
    end
    alias_method :[]=, :set

    # @!macro [attach] final_struct_set_predicate
    #
    #   Check the internal hash to unambiguously verify that the given
    #   attribute has been set.
    #
    #   @param [Symbol] field the field to get the value for
    #   @return [Boolean] true if the field has been set else false
    def set?(field)
      synchronize { ns_attribute_has_been_set?(field) }
    end

    # Get the current value of the given field if already set else set the value of
    # the given field to the given value.
    #
    # @param [Symbol] field the field to get or set the value for
    # @param [Object] value the value to set the field to when not previously set
    # @return [Object] the final value of the given field
    def get_or_set(field, value)
      synchronize { ns_attribute_has_been_set?(field) ? ns_get_attribute(field) : ns_set_attribute(field, value) }
    end

    # Get the current value of the given field if already set else return the given
    # default value.
    #
    # @param [Symbol] field the field to get the value for
    # @param [Object] default the value to return if the field has not been set
    # @return [Object] the value of the given field else the given default value
    def fetch(field, default)
      synchronize { ns_attribute_has_been_set?(field) ? ns_get_attribute(field) : default }
    end

    # Calls the block once for each attribute, passing the key/value pair as parameters.
    # If no block is given, an enumerator is returned instead.
    #
    # @yieldparam [Symbol] field the struct field for the current iteration
    # @yieldparam [Object] value the value of the current field
    #
    # @return [Enumerable] when no block is given
    def each_pair
      return enum_for(:each_pair) unless block_given?
      synchronize do
        @attribute_hash.each do |field, value|
          yield(field, value)
        end
      end
    end

    # Converts the `FinalStruct` to a `Hash` with keys representing each attribute
    # (as symbols) and their corresponding values.
    # 
    # @return [Hash] a `Hash` representing this struct
    def to_h
      synchronize { @attribute_hash.dup }
    end

    # Compares this object and other for equality. A `FinalStruct` is `eql?` to
    # other when other is a `FinalStruct` and the two objects have identical
    # fields and values.
    #
    # @param [Object] other the other record to compare for equality
    # @return [Boolean] true when equal else false
    def eql?(other)
      other.is_a?(self.class) && to_h == other.to_h
    end
    alias_method :==, :eql?

    # Describe the contents of this object in a string.
    #
    # @return [String] the string representation of this object
    #
    # @!visibility private
    def inspect
      state = to_h.to_s.gsub(/^{/, '').gsub(/}$/, '')
      "#<#{self.class} #{state}>"
    end
    alias_method :to_s, :inspect

    protected

    # @!macro final_struct_get_method
    # @!visibility private
    def ns_get_attribute(field)
      @attribute_hash[field.to_sym]
    end

    # @!macro final_struct_set_method
    # @!visibility private
    def ns_set_attribute(field, value)
      @attribute_hash[field.to_sym] = value
    end

    # @!macro final_struct_set_predicate
    # @!visibility private
    def ns_attribute_has_been_set?(field)
      @attribute_hash.has_key?(field.to_sym)
    end

    # Check the method name and args for signatures matching potential
    # final attribute reader, writer, and predicate methods. If the signature
    # matches a reader or predicate, treat the attribute as unset. If the
    # signature matches a writer, attempt to set the new attribute.
    #
    # @param [Symbol] symbol the name of the called function
    # @param [Array] args zero or more arguments
    # @return [Object] the result of the proxied method or the `super` call
    #
    # @!visibility private
    def method_missing(symbol, *args)
      if args.length == 1 && (match = /([^=]+)=$/.match(symbol))
        set(match[1], args.first)
      elsif args.length == 0 && (match = /([^\?]+)\?$/.match(symbol))
        set?(match[1])
      elsif args.length == 0
        get(symbol)
      else
        super
      end
    end
  end
end


================================================
FILE: lib/functional/final_var.rb
================================================
require 'functional/synchronization'

module Functional

  # An exception raised when an attempt is made to modify an
  # immutable object or attribute.
  FinalityError = Class.new(StandardError)

  # A thread safe object that holds a single value and is "final" (meaning
  # that the value can be set at most once after which it becomes immutable).
  # The value can be set at instantiation which will result in the object
  # becoming fully and immediately immutable. Attempting to set the value
  # once it has been set is a logical error and will result in an exception
  # being raised.
  #
  # @example Instanciation With No Value
  #   f = Functional::FinalVar.new
  #     #=> #<Functional::FinalVar unset>
  #   f.set?       #=> false
  #   f.value      #=> nil
  #   f.value = 42 #=> 42
  #   f.inspect
  #     #=> "#<Functional::FinalVar value=42>"
  #   f.set?       #=> true
  #   f.value      #=> 42
  #
  # @example Instanciation With an Initial Value
  #   f = Functional::FinalVar.new(42)
  #     #=> #<Functional::FinalVar value=42>
  #   f.set?       #=> true
  #   f.value      #=> 42
  #
  # @see Functional::FinalStruct
  # @see http://en.wikipedia.org/wiki/Final_(Java) Java `final` keyword
  #
  # @!macro [new] thread_safe_final_object
  #
  #   @note This is a write-once, read-many, thread safe object that can
  #     be used in concurrent systems. Thread safety guarantees *cannot* be made
  #     about objects contained *within* this object, however. Ruby variables are
  #     mutable references to mutable objects. This cannot be changed. The best
  #     practice it to only encapsulate immutable, frozen, or thread safe objects.
  #     Ultimately, thread safety is the responsibility of the programmer.
  class FinalVar < Synchronization::Object

    # @!visibility private
    NO_VALUE = Object.new.freeze

    # Create a new `FinalVar` with the given value or "unset" when
    # no value is given.
    #
    # @param [Object] value if given, the immutable value of the object
    def initialize(value = NO_VALUE)
      super
      synchronize{ @value = value }
    end

    # Get the current value or nil if unset.
    #
    # @return [Object] the current value or nil
    def get
      synchronize { has_been_set? ? @value : nil }
    end
    alias_method :value, :get

    # Set the value. Will raise an exception if already set.
    #
    # @param [Object] value the value to set
    # @return [Object] the new value
    # @raise [Functional::FinalityError] if the value has already been set
    def set(value)
      synchronize do
        if has_been_set?
          raise FinalityError.new('value has already been set')
        else
          @value = value
        end
      end
    end
    alias_method :value=, :set

    # Has the value been set?
    #
    # @return [Boolean] true when the value has been set else false
    def set?
      synchronize { has_been_set? }
    end
    alias_method :value?, :set?

    # Get the value if it has been set else set the value.
    #
    # @param [Object] value the value to set
    # @return [Object] the current value if already set else the new value
    def get_or_set(value)
      synchronize do
        if has_been_set?
          @value
        else
          @value = value
        end
      end
    end

    # Get the value if set else return the given default value.
    #
    # @param [Object] default the value to return if currently unset
    # @return [Object] the current value when set else the given default
    def fetch(default)
      synchronize { has_been_set? ? @value : default }
    end

    # Compares this object and other for equality. A `FinalVar` that is unset
    # is never equal to anything else (it represents a complete absence of value).
    # When set a `FinalVar` is equal to another `FinalVar` if they have the same
    # value. A `FinalVar` is equal to another object if its value is equal to
    # the other object using Ruby's normal equality rules.
    #
    # @param [Object] other the object to compare equality to
    # @return [Boolean] true if equal else false
    def eql?(other)
      if (val = fetch(NO_VALUE)) == NO_VALUE
        false
      elsif other.is_a?(FinalVar)
        val == other.value
      else
        val == other
      end
    end
    alias_method :==, :eql?

    # Describe the contents of this object in a string.
    #
    # @return [String] the string representation of this object
    #
    # @!visibility private
    def inspect
      if (val = fetch(NO_VALUE)) == NO_VALUE
        val = 'unset'
      else
        val = "value=#{val.is_a?(String) ? ('"' + val + '"') : val }"
      end
      "#<#{self.class} #{val}>"
    end

    # Describe the contents of this object in a string.
    #
    # @return [String] the string representation of this object
    #
    # @!visibility private
    def to_s
      value.to_s
    end

    private

    # Checks the set status without locking the mutex.
    # @return [Boolean] true when set else false
    def has_been_set?
      @value != NO_VALUE
    end
  end
end


================================================
FILE: lib/functional/memo.rb
================================================
require 'functional/synchronization'

module Functional

  # Memoization is a technique for optimizing functions that are time-consuming
  # and/or involve expensive calculations. Every time a memoized function is
  # called the result is caches with reference to the given parameters.
  # Subsequent calls to the function that use the same parameters will return
  # the cached result. As a result the response time for frequently called
  # functions is vastly increased (after the first call with any given set of)
  # arguments, at the cost of increased memory usage (the cache).
  #
  # {include:file:doc/memo.md}
  #
  # @note Memoized method calls are thread safe and can safely be used in
  #   concurrent systems. Declaring memoization on a function is *not* thread
  #   safe and should only be done during application initialization.
  module Memo

    # @!visibility private
    def self.extended(base)
      base.extend(ClassMethods)
      base.send(:__method_memos__=, {})
      super(base)
    end

    # @!visibility private
    def self.included(base)
      base.extend(ClassMethods)
      base.send(:__method_memos__=, {})
      super(base)
    end

    # @!visibility private
    module ClassMethods

      # @!visibility private
      class Memoizer < Synchronization::Object
        attr_reader :function, :cache, :max_cache
        def initialize(function, max_cache)
          super
          synchronize do
            @function = function
            @max_cache = max_cache
            @cache = {}
          end
        end
        def max_cache?
          max_cache > 0 && cache.size >= max_cache
        end
        public :synchronize
      end
      private_constant :Memoizer

      # @!visibility private
      attr_accessor :__method_memos__

      # Returns a memoized version of a referentially transparent function. The
      # memoized version of the function keeps a cache of the mapping from
      # arguments to results and, when calls with the same arguments are
      # repeated often, has higher performance at the expense of higher memory
      # use.
      #
      # @param [Symbol] func the class/module function to memoize
      # @param [Hash] opts the options controlling memoization
      # @option opts [Fixnum] :at_most the maximum number of memos to store in
      #   the cache; a value of zero (the default) or `nil` indicates no limit
      #
      # @raise [ArgumentError] when the method has already been memoized
      # @raise [ArgumentError] when :at_most option is a negative number
      def memoize(func, opts = {})
        func = func.to_sym
        max_cache = opts[:at_most].to_i
        raise ArgumentError.new("method :#{func} has already been memoized") if __method_memos__.has_key?(func)
        raise ArgumentError.new(':max_cache must be > 0') if max_cache < 0
        __method_memos__[func] = Memoizer.new(method(func), max_cache.to_i)
        __define_memo_proxy__(func)
        nil
      end

      # @!visibility private
      def __define_memo_proxy__(func)
        self.class_eval <<-RUBY
          def self.#{func}(*args, &block)
            self.__proxy_memoized_method__(:#{func}, *args, &block)
          end
        RUBY
      end

      # @!visibility private
      def __proxy_memoized_method__(func, *args, &block)
        memo = self.__method_memos__[func]
        memo.synchronize do
          if block_given?
            memo.function.call(*args, &block)
          elsif memo.cache.has_key?(args)
            memo.cache[args]
          else
            result = memo.function.call(*args)
            memo.cache[args] = result unless memo.max_cache?
          end
        end
      end
    end
  end
end


================================================
FILE: lib/functional/method_signature.rb
================================================
module Functional

  module PatternMatching

    # @!visibility private
    #
    # Helper functions used when pattern matching runtime arguments against
    # a method defined with the `defn` function of Functional::PatternMatching.
    module MethodSignature
      extend self

      # Do the given arguments match the given function pattern?
      #
      # @return [Boolean] true when there is a match else false
      def match?(pattern, args)
        return false unless valid_pattern?(args, pattern)

        pattern.length.times.all? do |index|
          param = pattern[index]
          arg = args[index]

          all_param_and_last_arg?(pattern, param, index) ||
            arg_is_type_of_param?(param, arg) ||
            hash_param_with_matching_arg?(param, arg) ||
            param_matches_arg?(param, arg)
        end
      end

      # Is the given pattern a valid pattern with respect to the given
      # runtime arguments?
      #
      # @return [Boolean] true when the pattern is valid else false
      def valid_pattern?(args, pattern)
        (pattern.last == PatternMatching::ALL && args.length >= pattern.length) \
          || (args.length == pattern.length)
      end

      # Is this the last parameter and is it `ALL`?
      #
      # @return [Boolean] true when matching else false
      def all_param_and_last_arg?(pattern, param, index)
        param == PatternMatching::ALL && index+1 == pattern.length
      end

      # Is the parameter a class and is the provided argument an instance
      # of that class?
      #
      # @return [Boolean] true when matching else false
      def arg_is_type_of_param?(param, arg)
        param.is_a?(Class) && arg.is_a?(param)
      end

      # Is the given parameter a Hash and does it match the given
      # runtime argument?
      #
      # @return [Boolean] true when matching else false
      def hash_param_with_matching_arg?(param, arg)
        param.is_a?(Hash) && arg.is_a?(Hash) && ! param.empty? && param.all? do |key, value|
          arg.has_key?(key) && (value == PatternMatching::UNBOUND || arg[key] == value)
        end
      end

      # Does the given parameter exactly match the given runtime
      # argument or is the parameter `UNBOUND`?
      #
      # @return [Boolean] true when matching else false
      def param_matches_arg?(param, arg)
        param == PatternMatching::UNBOUND || param == arg
      end
    end
    private_constant :MethodSignature
  end
end


================================================
FILE: lib/functional/option.rb
================================================
require 'functional/abstract_struct'
require 'functional/either'
require 'functional/protocol'
require 'functional/synchronization'

Functional::SpecifyProtocol(:Option) do
  instance_method :some?, 0
  instance_method :none?, 0
  instance_method :some, 0
end

module Functional

  # An optional value that may be none (no value) or some (a value).
  # This type is a replacement for the use of nil with better type checks. 
  # It is an immutable data structure that extends `AbstractStruct`.
  #
  # @see http://functionaljava.googlecode.com/svn/artifacts/3.0/javadoc/index.html Functional Java
  #
  # @!macro thread_safe_immutable_object
  class Option < Synchronization::Object
    include AbstractStruct

    # @!visibility private 
    NO_OPTION = Object.new.freeze

    self.datatype = :option
    self.fields = [:some].freeze

    private_class_method :new

    # The reason for the absence of a value when none,
    # defaults to nil
    attr_reader :reason

    class << self

      # Construct an `Option` with no value.
      #
      # @return [Option] the new option
      def none(reason = nil)
        new(nil, true, reason).freeze
      end

      # Construct an `Option` with the given value.
      #
      # @param [Object] value the value of the option
      # @return [Option] the new option
      def some(value)
        new(value, false).freeze
      end
    end

    # Does the option have a value?
    #
    # @return [Boolean] true if some else false
    def some?
      ! none?
    end
    alias_method :value?, :some?
    alias_method :fulfilled?, :some?

    # Is the option absent a value?
    #
    # @return [Boolean] true if none else false
    def none?
      @none
    end
    alias_method :reason?, :none?
    alias_method :rejected?, :none?

    # The value of this option.
    #
    # @return [Object] the value when some else nil
    def some
      to_h[:some]
    end
    alias_method :value, :some

    # Returns the length of this optional value;
    # 1 if there is a value, 0 otherwise. 
    #
    # @return [Fixnum] The length of this optional value;
    #   1 if there is a value, 0 otherwise.
    def length
      none? ? 0 : 1
    end
    alias_method :size, :length

    # Perform a logical `and` operation against this option and the
    # provided option or block. Returns true if this option is some and:
    #
    # * other is an `Option` with some value
    # * other is a truthy value (not nil or false)
    # * the result of the block is a truthy value
    #
    # If a block is given the value of the current option is passed to the
    # block and the result of block processing will be evaluated for its
    # truthiness. An exception will be raised if an other value and a
    # block are both provided.
    #
    # @param [Object] other the value to be evaluated against this option
    # @yieldparam [Object] value the value of this option when some
    # @return [Boolean] true when the union succeeds else false
    # @raise [ArgumentError] when given both other and a block
    def and(other = NO_OPTION)
      raise ArgumentError.new('cannot give both an option and a block') if other != NO_OPTION && block_given?
      return false if none?

      if block_given?
        !! yield(some)
      elsif Protocol::Satisfy? other, :Option
        other.some?
      else
        !! other
      end
    end

    # Perform a logical `or` operation against this option and the
    # provided option or block. Returns true if this option is some.
    # If this option is none it returns true if:
    #
    # * other is an `Option` with some value
    # * other is a truthy value (not nil or false)
    # * the result of the block is a truthy value
    #
    # If a block is given the value of the result of block processing
    # will be evaluated for its truthiness. An exception will be raised
    # if an other value and a block are both provided.
    #
    # @param [Object] other the value to be evaluated against this option
    # @return [Boolean] true when the intersection succeeds else false
    # @raise [ArgumentError] when given both other and a block
    def or(other = NO_OPTION)
      raise ArgumentError.new('cannot give both an option and a block') if other != NO_OPTION && block_given?
      return true if some?

      if block_given?
        !! yield
      elsif Protocol::Satisfy? other, :Option
        other.some?
      else
        !! other
      end
    end

    # Returns the value of this option when some else returns the
    # value of the other option or block. When the other is also an
    # option its some value is returned. When the other is any other
    # value it is simply passed through. When a block is provided the
    # block is processed and the return value of the block is returned.
    # An exception will be raised if an other value and a block are
    # both provided.
    #
    # @param [Object] other the value to be evaluated when this is none
    # @return [Object] this value when some else the value of other
    # @raise [ArgumentError] when given both other and a block
    def else(other = NO_OPTION)
      raise ArgumentError.new('cannot give both an option and a block') if other != NO_OPTION && block_given?
      return some if some?

      if block_given?
        yield
      elsif Protocol::Satisfy? other, :Option
        other.some
      else
        other
      end
    end

    # If the condition satisfies, return the given A in some, otherwise, none.
    #
    # @param [Object] value The some value to use if the condition satisfies.
    # @param [Boolean] condition The condition to test (when no block given).
    # @yield The condition to test (when no condition given).
    #
    # @return [Option] A constructed option based on the given condition.
    #
    # @raise [ArgumentError] When both a condition and a block are given.
    def self.iff(value, condition = NO_OPTION)
      raise ArgumentError.new('requires either a condition or a block, not both') if condition != NO_OPTION && block_given?
      condition = block_given? ? yield : !! condition
      condition ? some(value) : none
    end

    # @!macro inspect_method
    def inspect
      super.gsub(/ :some/, " (#{some? ? 'some' : 'none'}) :some")
    end
    alias_method :to_s, :inspect

    private

    # Create a new Option with the given value and disposition.
    #
    # @param [Object] value the value of this option
    # @param [Boolean] none is this option absent a value?
    # @param [Object] reason the reason for the absense of a value
    #
    # @!visibility private 
    def initialize(value, none, reason = nil)
      super
      @none = none
      @reason = none ? reason : nil
      hsh = none ? {some: nil} : {some: value}
      set_data_hash(hsh)
      set_values_array(hsh.values)
      ensure_ivar_visibility!
    end
  end
end


================================================
FILE: lib/functional/pattern_matching.rb
================================================
require 'functional/method_signature'

module Functional

  # As much as I love Ruby I've always been a little disappointed that Ruby
  # doesn't support function overloading. Function overloading tends to reduce
  # branching and keep function signatures simpler. No sweat, I learned to do
  # without. Then I started programming in Erlang. My favorite Erlang feature
  # is, without question, pattern matching. Pattern matching is like function
  # overloading cranked to 11. So one day I was musing on Twitter that I'd like
  # to see Erlang-stype pattern matching in Ruby and one of my friends responded
  # "Build it!" So I did. And here it is.
  #
  # {include:file:doc/pattern_matching.md}
  module PatternMatching

    # A parameter that is required but that can take any value.
    # @!visibility private
    UNBOUND = Object.new.freeze

    # A match for one or more parameters in the last position of the match.
    # @!visibility private
    ALL = Object.new.freeze

    private

    # A guard clause on a pattern match.
    # @!visibility private
    GuardClause = Class.new do
      def initialize(function, clazz, pattern)
        @function = function
        @clazz = clazz
        @pattern = pattern
      end
      def when(&block)
        unless block_given?
          raise ArgumentError.new("block missing for `when` guard on function `#{@function}` of class #{@clazz}")
        end
        @pattern.guard = block
        self
      end
    end
    private_constant :GuardClause

    # @!visibility private
    FunctionPattern = Struct.new(:function, :args, :body, :guard)
    private_constant :FunctionPattern

    # @!visibility private
    def __unbound_args__(match, args)
      argv = []
      match.args.each_with_index do |p, i|
        if p == ALL && i == match.args.length-1
          # when got ALL, then push all to the end to the list of args,
          # so we can get them as usual *args in matched method
          argv.concat args[(i..args.length)]
        elsif p.is_a?(Hash) && p.values.include?(UNBOUND)
          p.each do |key, value|
            argv << args[i][key] if value == UNBOUND
          end
        elsif p.is_a?(Hash) || p == UNBOUND || p.is_a?(Class)
          argv << args[i]
        end
      end
      argv
    end

    def __pass_guard__?(matcher, args)
      matcher.guard.nil? ||
        self.instance_exec(*__unbound_args__(matcher, args), &matcher.guard)
    end

    # @!visibility private
    def __pattern_match__(clazz, function, *args, &block)
      args = args.first
      matchers = clazz.__function_pattern_matches__.fetch(function, [])
      matchers.detect do |matcher|
        MethodSignature.match?(matcher.args, args) && __pass_guard__?(matcher, args)
      end
    end

    # @!visibility private
    def self.included(base)
      base.extend(ClassMethods)
      super(base)
    end

    # Class methods added to a class that includes {Functional::PatternMatching}
    # @!visibility private
    module ClassMethods

      # @!visibility private
      def _()
        UNBOUND
      end

      # @!visibility private
      def defn(function, *args, &block)
        unless block_given?
          raise ArgumentError.new("block missing for definition of function `#{function}` on class #{self}")
        end

        # Check that number of free variables in pattern match method's arity
        pat_arity = __pattern_arity__(args)
        unless pat_arity == block.arity
          raise ArgumentError.new("Pattern and block arity mismatch: "\
                                    "#{pat_arity}, #{block.arity}")
        end

        # add a new pattern for this function
        pattern = __register_pattern__(function, *args, &block)

        # define the delegator function if it doesn't exist yet
        unless self.instance_methods(false).include?(function)
          __define_method_with_matching__(function)
        end

        # return a guard clause to be added to the pattern
        GuardClause.new(function, self, pattern)
      end

      # @!visibility private
      # define an arity -1 function that dispatches to the appropriate
      # pattern match variant or raises an exception
      def __define_method_with_matching__(function)
        define_method(function) do |*args, &block|
          begin
            # get the collection of matched patterns for this function
            # use owner to ensure we climb the inheritance tree
            match = __pattern_match__(self.method(function).owner, function, args, block)
            if match
              # call the matched function
              argv = __unbound_args__(match, args)
              self.instance_exec(*argv, &match.body)
            elsif defined?(super)
              # delegate to the superclass
              super(*args, &block)
            else
              raise NoMethodError.new("no method `#{function}` matching "\
                "#{args} found for class #{self.class}")
            end
          end
        end
      end

      # @!visibility private
      def __function_pattern_matches__
        @__function_pattern_matches__ ||= Hash.new
      end

      # @!visibility private
      def __register_pattern__(function, *args, &block)
        block = Proc.new{} unless block_given?
        pattern = FunctionPattern.new(function, args, block)
        patterns = self.__function_pattern_matches__.fetch(function, [])
        patterns << pattern
        self.__function_pattern_matches__[function] = patterns
        pattern
      end

      # @!visibility private
      def __pattern_arity__(pat)
        r = pat.reduce(0) do |acc, v|
          if v.is_a?(Hash) 
            ub = v.values.count { |e| e == UNBOUND }
            # if hash have UNBOUND then treat each unbound as separate arg
            # alse all hash is one arg
            ub > 0 ? acc + ub : acc + 1
          elsif v == ALL || v == UNBOUND || v.is_a?(Class)
            acc + 1
          else
            acc
          end
        end
        pat.last == ALL ? -r : r
      end

    end
  end
end


================================================
FILE: lib/functional/protocol.rb
================================================
require 'functional/protocol_info'

module Functional

  # An exception indicating a problem during protocol processing.
  ProtocolError = Class.new(StandardError)

  # Specify a new protocol or retrieve the specification of an existing
  # protocol.
  #
  # When called without a block the global protocol registry will be searched
  # for a protocol with the matching name. If found the corresponding
  # {Functional::ProtocolInfo} object will be returned. If not found `nil` will
  # be returned.
  #
  # When called with a block, a new protocol with the given name will be
  # created and the block will be processed to provide the specifiction.
  # When successful the new {Functional::ProtocolInfo} object will be returned.
  # An exception will be raised if a protocol with the same name already
  # exists.
  #
  # @example
  #   Functional::SpecifyProtocol(:Queue) do
  #     instance_method :push, 1
  #     instance_method :pop, 0
  #     instance_method :length, 0
  #   end
  #
  # @param [Symbol] name The global name of the new protocol
  # @yield The protocol definition
  # @return [Functional::ProtocolInfo] the newly created or already existing
  #   protocol specification
  #
  # @raise [Functional::ProtocolError] when attempting to specify a protocol
  #   that has already been specified.
  #
  # @see Functional::Protocol
  def SpecifyProtocol(name, &block)
    name = name.to_sym
    protocol_info = Protocol.class_variable_get(:@@info)[name]

    return protocol_info unless block_given?

    if block_given? && protocol_info
      raise ProtocolError.new(":#{name} has already been defined")
    end

    info = ProtocolInfo.new(name, &block)
    Protocol.class_variable_get(:@@info)[name] = info
  end
  module_function :SpecifyProtocol

  # Protocols provide a polymorphism and method-dispatch mechanism that eschews
  # strong typing and embraces the dynamic duck typing of Ruby. Rather than
  # interrogate a module, class, or object for its type and ancestry, protocols
  # allow modules, classes, and methods to be interrogated based on their behavior.
  # It is a logical extension of the `respond_to?` method, but vastly more powerful.
  #
  # {include:file:doc/protocol.md}
  module Protocol

    # The global registry of specified protocols.
    @@info = {}

    # Does the given module/class/object fully satisfy the given protocol(s)?
    #
    # @param [Object] target the method/class/object to interrogate
    # @param [Symbol] protocols one or more protocols to check against the target
    # @return [Boolean] true if the target satisfies all given protocols else false
    #
    # @raise [ArgumentError] when no protocols given
    def Satisfy?(target, *protocols)
      raise ArgumentError.new('no protocols given') if protocols.empty?
      protocols.all?{|protocol| Protocol.satisfies?(target, protocol.to_sym) }
    end
    module_function :Satisfy?

    # Does the given module/class/object fully satisfy the given protocol(s)?
    # Raises a {Functional::ProtocolError} on failure.
    #
    # @param [Object] target the method/class/object to interrogate
    # @param [Symbol] protocols one or more protocols to check against the target
    # @return [Symbol] the target
    #
    # @raise [Functional::ProtocolError] when one or more protocols are not satisfied
    # @raise [ArgumentError] when no protocols given
    def Satisfy!(target, *protocols)
      Protocol::Satisfy?(target, *protocols) or
        Protocol.error(target, 'does not', *protocols)
      target
    end
    module_function :Satisfy!

    # Have the given protocols been specified?
    #
    # @param [Symbol] protocols the list of protocols to check
    # @return [Boolean] true if all given protocols have been specified else false
    #
    # @raise [ArgumentError] when no protocols are given
    def Specified?(*protocols)
      raise ArgumentError.new('no protocols given') if protocols.empty?
      Protocol.unspecified(*protocols).empty?
    end
    module_function :Specified?

    # Have the given protocols been specified?
    # Raises a {Functional::ProtocolError} on failure.
    #
    # @param [Symbol] protocols the list of protocols to check
    # @return [Boolean] true if all given protocols have been specified
    #
    # @raise [Functional::ProtocolError] if one or more of the given protocols have
    #   not been specified
    # @raise [ArgumentError] when no protocols are given
    def Specified!(*protocols)
      raise ArgumentError.new('no protocols given') if protocols.empty?
      (unspecified = Protocol.unspecified(*protocols)).empty? or
        raise ProtocolError.new("The following protocols are unspecified: :#{unspecified.join('; :')}.")
    end
    module_function :Specified!

    private

    # Does the target satisfy the given protocol?
    #
    # @param [Object] target the module/class/object to check
    # @param [Symbol] protocol the protocol to check against the target
    # @return [Boolean] true if the target satisfies the protocol else false
    def self.satisfies?(target, protocol)
      info = @@info[protocol]
      return info && info.satisfies?(target)
    end

    # Reduces a list of protocols to a list of unspecified protocols.
    #
    # @param [Symbol] protocols the list of protocols to check
    # @return [Array] zero or more unspecified protocols
    def self.unspecified(*protocols)
      protocols.drop_while do |protocol|
        @@info.has_key? protocol.to_sym
      end
    end

    # Raise a {Functional::ProtocolError} formatted with the given data.
    #
    # @param [Object] target the object that was being interrogated
    # @param [String] message the message fragment to inject into the error
    # @param [Symbol] protocols list of protocols that were being checked against the target
    #
    # @raise [Functional::ProtocolError] the formatted exception object
    def self.error(target, message, *protocols)
      target = target.class unless target.is_a?(Module)
      raise ProtocolError,
        "Value (#{target.class}) '#{target}' #{message} behave as all of: :#{protocols.join('; :')}."
    end
  end
end


================================================
FILE: lib/functional/protocol_info.rb
================================================
require 'functional/synchronization'

module Functional

  # An immutable object describing a single protocol and capable of building
  # itself from a block. Used by {Functional#SpecifyProtocol}.
  # 
  # @see Functional::Protocol
  class ProtocolInfo < Synchronization::Object

    # The symbolic name of the protocol
    attr_reader :name

    # Process a protocol specification block and build a new object.
    #
    # @param [Symbol] name the symbolic name of the protocol
    # @yield self to the given specification block
    # @return [Functional::ProtocolInfo] the new info object, frozen
    #
    # @raise [ArgumentError] when name is nil or an empty string
    # @raise [ArgumentError] when no block given
    def initialize(name, &specification)
      raise ArgumentError.new('no block given') unless block_given?
      raise ArgumentError.new('no name given') if name.nil? || name.empty?
      super
      @name = name.to_sym
      @info = Info.new({}, {}, [])
      self.instance_eval(&specification)
      @info.each_pair{|col, _| col.freeze}
      @info.freeze
      ensure_ivar_visibility!
      self.freeze
    end

    # The instance methods expected by this protocol.
    #
    # @return [Hash] a frozen hash of all instance method names and their
    #   expected arity for this protocol
    def instance_methods
      @info.instance_methods
    end

    # The class methods expected by this protocol.
    #
    # @return [Hash] a frozen hash of all class method names and their
    #   expected arity for this protocol
    def class_methods
      @info.class_methods
    end

    # The constants expected by this protocol.
    #
    # @return [Array] a frozen list of the constants expected by this protocol
    def constants
      @info.constants
    end

    # Does the given module/class/object satisfy this protocol?
    #
    # @return [Boolean] true if the target satisfies this protocol else false
    def satisfies?(target)
      satisfies_constants?(target) &&
        satisfies_instance_methods?(target) &&
        satisfies_class_methods?(target)
    end

    private

    # Data structure for encapsulating the protocol info data.
    # @!visibility private
    Info = Struct.new(:instance_methods, :class_methods, :constants)

    # Does the target satisfy the constants expected by this protocol?
    #
    # @param [target] target the module/class/object to interrogate
    # @return [Boolean] true when satisfied else false
    def satisfies_constants?(target)
      clazz = target.is_a?(Module) ? target : target.class
      @info.constants.all?{|constant| clazz.const_defined?(constant) }
    end

    # Does the target satisfy the instance methods expected by this protocol?
    #
    # @param [target] target the module/class/object to interrogate
    # @return [Boolean] true when satisfied else false
    def satisfies_instance_methods?(target)
      @info.instance_methods.all? do |method, arity|
        if target.is_a? Module
          target.method_defined?(method) && check_arity?(target.instance_method(method), arity)
        else
          target.respond_to?(method) && check_arity?(target.method(method), arity)
        end
      end
    end


    # Does the target satisfy the class methods expected by this protocol?
    #
    # @param [target] target the module/class/object to interrogate
    # @return [Boolean] true when satisfied else false
    def satisfies_class_methods?(target)
      clazz = target.is_a?(Module) ? target : target.class
      @info.class_methods.all? do |method, arity|
        break false unless clazz.respond_to? method
        method = clazz.method(method)
        check_arity?(method, arity)
      end
    end

    # Does the given method have the expected arity? Returns true
    # if the arity of the method is `-1` (variable length argument list
    # with no required arguments), when expected is `nil` (indicating any
    # arity is acceptable), or the arity of the method exactly matches the
    # expected arity.
    #
    # @param [Method] method the method object to interrogate
    # @param [Fixnum] expected the expected arity
    # @return [Boolean] true when an acceptable match else false
    #
    # @see http://www.ruby-doc.org/core-2.1.2/Method.html#method-i-arity Method#arity
    def check_arity?(method, expected)
      arity = method.arity
      expected.nil? || arity == -1 || expected == arity
    end

    #################################################################
    # DSL methods

    # Specify an instance method.
    #
    # @param [Symbol] name the name of the method
    # @param [Fixnum] arity the required arity
    def instance_method(name, arity = nil)
      arity = arity.to_i unless arity.nil?
      @info.instance_methods[name.to_sym] = arity
    end

    # Specify a class method.
    #
    # @param [Symbol] name the name of the method
    # @param [Fixnum] arity the required arity
    def class_method(name, arity = nil)
      arity = arity.to_i unless arity.nil?
      @info.class_methods[name.to_sym] = arity
    end

    # Specify an instance reader attribute.
    #
    # @param [Symbol] name the name of the attribute
    def attr_reader(name)
      instance_method(name, 0)
    end

    # Specify an instance writer attribute.
    #
    # @param [Symbol] name the name of the attribute
    def attr_writer(name)
      instance_method("#{name}=".to_sym, 1)
    end

    # Specify an instance accessor attribute.
    #
    # @param [Symbol] name the name of the attribute
    def attr_accessor(name)
      attr_reader(name)
      attr_writer(name)
    end

    # Specify a class reader attribute.
    #
    # @param [Symbol] name the name of the attribute
    def class_attr_reader(name)
      class_method(name, 0)
    end

    # Specify a class writer attribute.
    #
    # @param [Symbol] name the name of the attribute
    def class_attr_writer(name)
      class_method("#{name}=".to_sym, 1)
    end

    # Specify a class accessor attribute.
    #
    # @param [Symbol] name the name of the attribute
    def class_attr_accessor(name)
      class_attr_reader(name)
      class_attr_writer(name)
    end

    # Specify a constant.
    #
    # @param [Symbol] name the name of the constant
    def constant(name)
      @info.constants << name.to_sym
    end
  end
end


================================================
FILE: lib/functional/record.rb
================================================
require 'functional/abstract_struct'
require 'functional/protocol'
require 'functional/type_check'

module Functional

  # An immutable data structure with multiple data fields. A `Record` is a
  # convenient way to bundle a number of field attributes together,
  # using accessor methods, without having to write an explicit class.
  # The `Record` module generates new `AbstractStruct` subclasses that hold a
  # set of fields with a reader method for each field.
  #
  # A `Record` is very similar to a Ruby `Struct` and shares many of its behaviors
  # and attributes. Unlike a # Ruby `Struct`, a `Record` is immutable: its values
  # are set at construction and can never be changed. Divergence between the two
  # classes derive from this core difference.
  #
  # {include:file:doc/record.md}
  #
  # @see Functional::Union
  # @see Functional::Protocol
  # @see Functional::TypeCheck
  #
  # @!macro thread_safe_immutable_object
  module Record
    extend self

    # Create a new record class with the given fields.
    #
    # @return [Functional::AbstractStruct] the new record subclass
    # @raise [ArgumentError] no fields specified or an invalid type
    #   specification is given
    def new(*fields, &block)
      raise ArgumentError.new('no fields provided') if fields.empty?

      name = nil
      types = nil

      # check if a name for registration is given
      if fields.first.is_a?(String)
        name = fields.first
        fields = fields[1..fields.length-1]
      end

      # check for a set of type/protocol specifications
      if fields.size == 1 && fields.first.respond_to?(:to_h)
        types = fields.first
        fields = fields.first.keys
        check_types!(types)
      end

      build(name, fields, types, &block)
    rescue
      raise ArgumentError.new('invalid specification')
    end

    private

    # @!visibility private
    #
    # A set of restrictions governing the creation of a new record.
    class Restrictions
      include Protocol
      include TypeCheck

      # Create a new restrictions object by processing the given
      # block. The block should be the DSL for defining a record class.
      #
      # @param [Hash] types a hash of fields and the associated type/protocol
      #   when type/protocol checking is among the restrictions
      # @param [Proc] block A DSL definition of a new record.
      # @yield A DSL definition of a new record.
      def initialize(types = nil, &block)
        @types = types
        @required = []
        @defaults = {}
        instance_eval(&block) if block_given?
        @required.freeze
        @defaults.freeze
        self.freeze
      end

      # DSL method for declaring one or more fields to be mandatory.
      #
      # @param [Symbol] fields zero or more mandatory fields
      def mandatory(*fields)
        @required.concat(fields.collect{|field| field.to_sym})
      end

      # DSL method for declaring a default value for a field
      #
      # @param [Symbol] field the field to be given a default value
      # @param [Object] value the default value of the field
      def default(field, value)
        @defaults[field] = value
      end

      # Clone a default value if it is cloneable. Else just return
      # the value.
      #
      # @param [Symbol] field the name of the field from which the
      #   default value is to be cloned.
      # @return [Object] a clone of the value or the value if uncloneable
      def clone_default(field)
        value = @defaults[field]
        value = value.clone unless uncloneable?(value)
      rescue TypeError
        # can't be cloned
      ensure
        return value
      end

      # Validate the record data against this set of restrictions.
      #
      # @param [Hash] data the data hash
      # @raise [ArgumentError] when the data does not match the restrictions
      def validate!(data)
        validate_mandatory!(data)
        validate_types!(data)
      end

      private

      # Check the given data hash to see if it contains non-nil values for
      # all mandatory fields.
      #
      # @param [Hash] data the data hash
      # @raise [ArgumentError] if any mandatory fields are missing
      def validate_mandatory!(data)
        if data.any?{|k,v| @required.include?(k) && v.nil? }
          raise ArgumentError.new('mandatory fields must not be nil')
        end
      end

      # Validate the record data against a type/protocol specification.
      #
      # @param [Hash] data the data hash
      # @raise [ArgumentError] when the data does not match the specification
      def validate_types!(data)
        return if @types.nil?
        @types.each do |field, type|
          value = data[field]
          next if value.nil?
          if type.is_a? Module
            raise ArgumentError.new("'#{field}' must be of type #{type}") unless Type?(value, type)
          else
            raise ArgumentError.new("'#{field}' must stasify the protocol :#{type}") unless Satisfy?(value, type)
          end
        end
      end

      # Is the given object uncloneable?
      #
      # @param [Object] object the object to check
      # @return [Boolean] true if the object cannot be cloned else false
      def uncloneable?(object)
        Type? object, NilClass, TrueClass, FalseClass, Fixnum, Bignum, Float
      end
    end
    private_constant :Restrictions

    # Validate the given type/protocol specification.
    #
    # @param [Hash] types the type specification
    # @raise [ArgumentError] when the specification is not valid
    def check_types!(types)
      return if types.nil?
      unless types.all?{|k,v| v.is_a?(Module) || v.is_a?(Symbol) }
        raise ArgumentError.new('invalid specification')
      end
    end

    # Use the given `AbstractStruct` class and build the methods necessary
    # to support the given data fields.
    #
    # @param [String] name the name under which to register the record when given
    # @param [Array] fields the list of symbolic names for all data fields
    # @return [Functional::AbstractStruct] the record class
    def build(name, fields, types, &block)
      fields = [name].concat(fields) unless name.nil?
      record, fields = AbstractStruct.define_class(self, :record, fields)
      record.class_variable_set(:@@restrictions, Restrictions.new(types, &block))
      define_initializer(record)
      fields.each do |field|
        define_reader(record, field)
      end
      record
    end

    # Define an initializer method on the given record class.
    #
    # @param [Functional::AbstractStruct] record the new record class
    # @return [Functional::AbstractStruct] the record class
    def define_initializer(record)
      record.send(:define_method, :initialize) do |data = {}|
        super()
        restrictions = record.class_variable_get(:@@restrictions)
        data = record.fields.reduce({}) do |memo, field|
          memo[field] = data.fetch(field, restrictions.clone_default(field))
          memo
        end
        restrictions.validate!(data)
        set_data_hash(data)
        set_values_array(data.values)
        ensure_ivar_visibility!
        self.freeze
      end
      record
    end

    # Define a reader method on the given record class for the given data field.
    #
    # @param [Functional::AbstractStruct] record the new record class
    # @param [Symbol] field symbolic name of the current data field
    # @return [Functional::AbstractStruct] the record class
    def define_reader(record, field)
      record.send(:define_method, field) do
        to_h[field]
      end
      record
    end
  end
end


================================================
FILE: lib/functional/synchronization.rb
================================================
module Functional

  # @!visibility private
  #
  # Based on work originally done by Petr Chalupa (@pitr-ch) in Concurrent Ruby.
  # https://github.com/ruby-concurrency/concurrent-ruby/blob/master/lib/concurrent/synchronization/object.rb
  module Synchronization

    if defined?(RUBY_ENGINE) && RUBY_ENGINE == 'jruby'

      require 'jruby'

      # @!visibility private
      class Object

        # @!visibility private
        def initialize(*args)
        end

        protected

        # @!visibility private
        def synchronize
          JRuby.reference0(self).synchronized { yield }
        end

        # @!visibility private
        def ensure_ivar_visibility!
          # relying on undocumented behavior of JRuby, ivar access is volatile
        end
      end

    elsif defined?(RUBY_ENGINE) && RUBY_ENGINE == 'rbx'

      # @!visibility private
      class Object

        # @!visibility private
        def initialize(*args)
        end

        protected

        # @!visibility private
        def synchronize(&block)
          Rubinius.synchronize(self, &block)
        end

        # @!visibility private
        def ensure_ivar_visibility!
          # Rubinius instance variables are not volatile so we need to insert barrier
          Rubinius.memory_barrier
        end
      end

    else

      require 'thread'

      # @!visibility private
      class Object

        # @!visibility private
        def initialize(*args)
          @__lock__      = ::Mutex.new
          @__condition__ = ::ConditionVariable.new
        end

        protected

        # @!visibility private
        def synchronize
          if @__lock__.owned?
            yield
          else
            @__lock__.synchronize { yield }
          end
        end

        # @!visibility private
        def ensure_ivar_visibility!
          # relying on undocumented behavior of CRuby, GVL acquire has lock which ensures visibility of ivars
          # https://github.com/ruby/ruby/blob/ruby_2_2/thread_pthread.c#L204-L211
        end
      end
    end
  end
end


================================================
FILE: lib/functional/tuple.rb
================================================
require 'functional/synchronization'

module Functional

  # A tuple is a pure functional data strcture that is similar to an array but is
  # immutable and of fixed length. Tuples support many of the same operations as
  # array/list/vector.
  #
  # @note The current implementation uses simple Ruby arrays. This is likely to be
  #   very inefficient for all but the smallest tuples. The more items the tuple
  #   contains, the less efficient it will become. A future version will use a fast,
  #   immutable, persistent data structure such as a finger tree or a trie.
  #
  # @!macro thread_safe_immutable_object
  #
  # @see http://en.wikipedia.org/wiki/Tuple
  # @see http://msdn.microsoft.com/en-us/library/system.tuple.aspx
  # @see http://www.tutorialspoint.com/python/python_tuples.htm
  # @see http://en.cppreference.com/w/cpp/utility/tuple
  # @see http://docs.oracle.com/javaee/6/api/javax/persistence/Tuple.html
  # @see http://www.erlang.org/doc/reference_manual/data_types.html
  # @see http://www.erlang.org/doc/man/erlang.html#make_tuple-2
  # @see http://en.wikibooks.org/wiki/Haskell/Lists_and_tuples#Tuples
  class Tuple < Synchronization::Object

    # Create a new tuple with the given data items in the given order.
    #
    # @param [Array] data the data items to insert into the new tuple
    # @raise [ArgumentError] if data is not an array or does not implement `to_a`
    def initialize(data = [])
      raise ArgumentError.new('data is not an array') unless data.respond_to?(:to_a)
      super
      @data = data.to_a.dup.freeze
      self.freeze
      ensure_ivar_visibility!
    end

    # Retrieve the item at the given index. Indices begin at zero and increment
    # up, just like Ruby arrays. Negative indicies begin at -1, which represents the
    # last item in the tuple, and decrement toward the first item. If the
    # given index is out of range then `nil` is returned.
    #
    # @param [Fixnum] index the index of the item to be retrieved
    # @return [Object] the item at the given index or nil when index is out of bounds
    def at(index)
      @data[index]
    end
    alias_method :nth, :at
    alias_method :[], :at

    # Retrieve the item at the given index or return the given default value if the
    # index is out of bounds. The behavior of indicies follows the rules for the
    # `at` method.
    #
    # @param [Fixnum] index the index of the item to be retrieved
    # @param [Object] default the value to return when given an out of bounds index
    # @return [Object] the item at the given index or default when index is out of bounds
    #
    # @see Functional::Tuple#at
    def fetch(index, default)
      if index >= length || -index > length
        default
      else
        at(index)
      end
    end

    # The number of items in the tuple.
    #
    # @return [Fixnum] the number of items in the tuple
    def length
      @data.length
    end
    alias_method :size, :length

    # Returns a new tuple containing elements common to the two tuples, excluding any
    # duplicates. The order is preserved from the original tuple.
    #
    # @!macro [attach] tuple_method_param_other_return_tuple
    #   @param [Array] other the tuple or array-like object (responds to `to_a`) to operate on
    #   @return [Functional::Tuple] a new tuple with the appropriate items
    def intersect(other)
      Tuple.new(@data & other.to_a)
    end
    alias_method :&, :intersect

    # Returns a new tuple by joining self with other, excluding any duplicates and
    # preserving the order from the original tuple.
    #
    # @!macro tuple_method_param_other_return_tuple
    def union(other)
      Tuple.new(@data | other.to_a)
    end
    alias_method :|, :union

    # Returns a new tuple built by concatenating the two tuples
    # together to produce a third tuple.
    #
    # @!macro tuple_method_param_other_return_tuple
    def concat(other)
      Tuple.new(@data + other.to_a)
    end
    alias_method :+, :concat

    # Returns a new tuple that is a copy of the original tuple, removing any items that
    # also appear in other. The order is preserved from the original tuple.
    #
    # @!macro tuple_method_param_other_return_tuple
    def diff(other)
      Tuple.new(@data - other.to_a)
    end
    alias_method :-, :diff

    # Returns a new tuple built by concatenating the given number of copies of self.
    # Returns an empty tuple when the multiple is zero.
    #
    # @param [Fixnum] multiple the number of times to concatenate self
    # @return [Functional::Tuple] a new tuple with the appropriate items
    # @raise [ArgumentError] when multiple is a negative number
    def repeat(multiple)
      multiple = multiple.to_i
      raise ArgumentError.new('negative argument') if multiple < 0
      Tuple.new(@data * multiple)
    end
    alias_method :*, :repeat

    # Returns a new tuple by removing duplicate values in self.
    #
    # @return [Functional::Tuple] the new tuple with only unique items
    def uniq
      Tuple.new(@data.uniq)
    end

    # Calls the given block once for each element in self, passing that element as a parameter.
    # An Enumerator is returned if no block is given.
    #
    # @yieldparam [Object] item the current item
    # @return [Enumerable] when no block is given
    def each
      return enum_for(:each) unless block_given?
      @data.each do |item|
        yield(item)
      end
    end

    # Calls the given block once for each element in self, passing that element
    # and the current index as parameters. An Enumerator is returned if no block is given.
    #
    # @yieldparam [Object] item the current item
    # @yieldparam [Fixnum] index the index of the current item
    # @return [Enumerable] when no block is given
    def each_with_index
      return enum_for(:each_with_index) unless block_given?
      @data.each_with_index do |item, index|
        yield(item, index)
      end
    end

    # Calls the given block once for each element in self, passing that element
    # and a tuple with all the remaining items in the tuple. When the last item
    # is reached ab empty tuple is passed as the second parameter. This is the
    # classic functional programming `head|tail` list processing idiom.
    # An Enumerator is returned if no block is given.
    #
    # @yieldparam [Object] head the current item for this iteration
    # @yieldparam [Tuple] tail the remaining items (tail) or an empty tuple when
    #   processing the last item
    # @return [Enumerable] when no block is given
    def sequence
      return enum_for(:sequence) unless block_given?
      @data.length.times do |index|
        last = @data.length - 1
        if index == last
          yield(@data[index], Tuple.new)
        else
          yield(@data[index], Tuple.new(@data.slice(index+1..last)))
        end
      end
    end

    # Compares this object and other for equality. A tuple is `eql?` to
    # other when other is a tuple or an array-like object (any object that
    # responds to `to_a`) and the two objects have identical values in the
    # same foxed order.
    #
    # @param [Object] other the other tuple to compare for equality
    # @return [Boolean] true when equal else false
    def eql?(other)
      @data == other.to_a
    end
    alias_method :==, :eql?

    # Returns true if self contains no items.
    #
    # @return [Boolean] true when empty else false
    def empty?
      @data.empty?
    end

    # Returns the first element of the tuple or nil when empty.
    #
    # @return [Object] the first element or nil
    def first
      @data.first
    end
    alias_method :head, :first

    # Returns a tuple containing all the items in self after the first
    # item. Returns an empty tuple when empty or there is only one item.
    #
    # @return [Functional::Tuple] the tail of the tuple
    def rest
      if @data.length <= 1
        Tuple.new
      else
        Tuple.new(@data.slice(1..@data.length-1))
      end
    end
    alias_method :tail, :rest

    # Create a standard Ruby mutable array containing the tuple items
    # in the same order.
    #
    # @return [Array] the new array created from the tuple
    def to_a
      @data.dup
    end
    alias_method :to_ary, :to_a

    # Describe the contents of this object in a string.
    #
    # @return [String] the string representation of this object
    #
    # @!visibility private
    def inspect
      "#<#{self.class}: #{@data.to_s}>"
    end

    # Describe the contents of this object in a string that exactly
    # matches the string that would be created from an identical array.
    #
    # @return [String] the string representation of this object
    #
    # @!visibility private
    def to_s
      @data.to_s
    end
  end
end


================================================
FILE: lib/functional/type_check.rb
================================================
module Functional

  # Supplies type-checking helpers whenever included.
  #
  # @see http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/Actor/TypeCheck.html TypeCheck in Concurrent Ruby
  module TypeCheck

    # Performs an `is_a?` check of the given value object against the
    # given list of modules and/or classes.
    #
    # @param [Object] value the object to interrogate
    # @param [Module] types zero or more modules and/or classes to check
    #   the value against
    # @return [Boolean] true on success
    def Type?(value, *types)
      types.any? { |t| value.is_a? t }
    end
    module_function :Type?

    # Performs an `is_a?` check of the given value object against the
    # given list of modules and/or classes. Raises an exception on failure.
    #
    # @param [Object] value the object to interrogate
    # @param [Module] types zero or more modules and/or classes to check
    #   the value against
    # @return [Object] the value object
    #
    # @raise [Functional::TypeError] when the check fails
    def Type!(value, *types)
      Type?(value, *types) or
        TypeCheck.error(value, 'is not', types)
      value
    end
    module_function :Type!

    # Is the given value object is an instance of or descendant of
    # one of the classes/modules in the given list?
    #
    # Performs the check using the `===` operator.
    #
    # @param [Object] value the object to interrogate
    # @param [Module] types zero or more modules and/or classes to check
    #   the value against
    # @return [Boolean] true on success
    def Match?(value, *types)
      types.any? { |t| t === value }
    end
    module_function :Match?

    # Is the given value object is an instance of or descendant of
    # one of the classes/modules in the given list?  Raises an exception
    # on failure.
    #
    # Performs the check using the `===` operator.
    #
    # @param [Object] value the object to interrogate
    # @param [Module] types zero or more modules and/or classes to check
    #   the value against
    # @return [Object] the value object
    #
    # @raise [Functional::TypeError] when the check fails
    def Match!(value, *types)
      Match?(value, *types) or
        TypeCheck.error(value, 'is not matching', types)
      value
    end
    module_function :Match!

    # Is the given class a subclass or exact match of one or more
    # of the modules and/or classes in the given list?
    #
    # @param [Class] value the class to interrogate
    # @param [Class] types zero or more classes to check the value against
    #   the value against
    # @return [Boolean] true on success
    def Child?(value, *types)
      Type?(value, Class) &&
        types.any? { |t| value <= t }
    end
    module_function :Child?

    # Is the given class a subclass or exact match of one or more
    # of the modules and/or classes in the given list?
    #
    # @param [Class] value the class to interrogate
    # @param [Class] types zero or more classes to check the value against
    # @return [Class] the value class
    #
    # @raise [Functional::TypeError] when the check fails
    def Child!(value, *types)
      Child?(value, *types) or
        TypeCheck.error(value, 'is not child', types)
      value
    end
    module_function :Child!

    private

    # Create a {Functional::TypeError} object from the given data.
    #
    # @param [Object] value the class/method that was being interrogated
    # @param [String] message the message fragment to inject into the error
    # @param [Object] types list of modules and/or classes that were being
    #   checked against the value object
    #
    # @raise [Functional::TypeError] the formatted exception object
    def self.error(value, message, types)
      raise TypeError,
        "Value (#{value.class}) '#{value}' #{message} any of: #{types.join('; ')}."
    end
  end
end


================================================
FILE: lib/functional/union.rb
================================================
require 'functional/abstract_struct'
require 'functional/synchronization'

module Functional

  # An immutable data structure with multiple fields, only one of which
  # can be set at any given time. A `Union` is a convenient way to bundle a
  # number of field attributes together, using accessor methods, without having
  # to write an explicit class.
  #
  # The `Union` module generates new `AbstractStruct` subclasses that hold a set of
  # fields with one and only one value associated with a single field. For each
  # field a reader method is created along with a predicate and a factory. The
  # predicate method indicates whether or not the give field is set. The reader
  # method returns the value of that field or `nil` when not set. The factory
  # creates a new union with the appropriate field set with the given value.
  #
  # A `Union` is very similar to a Ruby `Struct` and shares many of its behaviors
  # and attributes. Where a `Struct` can have zero or more values, each of which is
  # assiciated with a field, a `Union` can have one and only one value. Unlike a
  # Ruby `Struct`, a `Union` is immutable: its value is set at construction and
  # it can never be changed. Divergence between the two classes derive from these
  # two core differences.
  #
  # @example Creating a New Class
  # 
  #   LeftRightCenter = Functional::Union.new(:left, :right, :center) #=> LeftRightCenter
  #   LeftRightCenter.ancestors #=> [LeftRightCenter, Functional::AbstractStruct... ]
  #   LeftRightCenter.fields   #=> [:left, :right, :center]
  #   
  #   prize = LeftRightCenter.right('One million dollars!') #=> #<union LeftRightCenter... >
  #   prize.fields #=> [:left, :right, :center]
  #   prize.values  #=> [nil, "One million dollars!", nil]
  #   
  #   prize.left?   #=> false
  #   prize.right?  #=> true
  #   prize.center? #=> false
  #   
  #   prize.left    #=> nil
  #   prize.right   #=> "One million dollars!"
  #   prize.center  #=> nil
  #
  # @example Registering a New Class with Union
  #
  #   Functional::Union.new('Suit', :clubs, :diamonds, :hearts, :spades)
  #    #=> Functional::Union::Suit
  #
  #   Functional::Union::Suit.hearts('Queen')
  #    #=> #<union Functional::Union::Suit :clubs=>nil, :diamonds=>nil, :hearts=>"Queen", :spades=>nil>
  #
  # @see Functional::Union
  # @see http://www.ruby-doc.org/core-2.1.2/Struct.html Ruby `Struct` class
  # @see http://en.wikipedia.org/wiki/Union_type "Union type" on Wikipedia
  #
  # @!macro thread_safe_immutable_object
  module Union
    extend self

    # Create a new union class with the given fields.
    #
    # @return [Functional::AbstractStruct] the new union subclass
    # @raise [ArgumentError] no fields specified
    def new(*fields)
      raise ArgumentError.new('no fields provided') if fields.empty?
      build(fields)
    end

    private

    # Use the given `AbstractStruct` class and build the methods necessary
    # to support the given data fields.
    #
    # @param [Array] fields the list of symbolic names for all data fields
    # @return [Functional::AbstractStruct] the union class
    def build(fields)
      union, fields = AbstractStruct.define_class(self, :union, fields)
      union.private_class_method(:new)
      define_properties(union)
      define_initializer(union)
      fields.each do |field|
        define_reader(union, field)
        define_predicate(union, field)
        define_factory(union, field)
      end
      union
    end

    # Define the `field` and `value` attribute readers on the given union class.
    #
    # @param [Functional::AbstractStruct] union the new union class
    # @return [Functional::AbstractStruct] the union class
    def define_properties(union)
      union.send(:attr_reader, :field)
      union.send(:attr_reader, :value)
      union
    end

    # Define a predicate method on the given union class for the given data field.
    #
    # @param [Functional::AbstractStruct] union the new union class
    # @param [Symbol] field symbolic name of the current data field
    # @return [Functional::AbstractStruct] the union class
    def define_predicate(union, field)
      union.send(:define_method, "#{field}?".to_sym) do
        @field == field
      end
      union
    end

    # Define a reader method on the given union class for the given data field.
    #
    # @param [Functional::AbstractStruct] union the new union class
    # @param [Symbol] field symbolic name of the current data field
    # @return [Functional::AbstractStruct] the union class
    def define_reader(union, field)
      union.send(:define_method, field) do
        send("#{field}?".to_sym) ? @value : nil
      end
      union
    end

    # Define an initializer method on the given union class.
    #
    # @param [Functional::AbstractStruct] union the new union class
    # @return [Functional::AbstractStruct] the union class
    def define_initializer(union)
      union.send(:define_method, :initialize) do |field, value|
        super()
        @field = field
        @value = value
        data = fields.reduce({}) do |memo, field|
          memo[field] = ( field == @field ? @value : nil )
          memo
        end
        set_data_hash(data)
        set_values_array(data.values)
        ensure_ivar_visibility!
        self.freeze
      end
      union
    end

    # Define a factory method on the given union class for the given data field.
    #
    # @param [Functional::AbstractStruct] union the new union class
    # @param [Symbol] field symbolic name of the current data field
    # @return [Functional::AbstractStruct] the union class
    def define_factory(union, field)
      union.class.send(:define_method, field) do |value|
        new(field, value).freeze
      end
      union
    end
  end
end


================================================
FILE: lib/functional/value_struct.rb
================================================
require 'functional/synchronization'

module Functional

  # A variation on Ruby's `OpenStruct` in which all fields are immutable and
  # set at instantiation. For compatibility with {Functional::FinalStruct}, 
  # predicate methods exist for all potential fields and these predicates
  # indicate if the field has been set. Calling a predicate method for a field
  # that does not exist on the struct will return false.
  #
  # Unlike {Functional::Record}, which returns a new class which can be used to
  # create immutable objects, `ValueStruct` creates simple immutable objects.
  #
  # @example Instanciation
  #   name = Functional::ValueStruct.new(first: 'Douglas', last: 'Adams')
  #
  #   name.first   #=> 'Douglas'
  #   name.last    #=> 'Adams'
  #   name.first?  #=> true
  #   name.last?   #=> true
  #   name.middle? #=> false
  #
  # @see Functional::Record
  # @see Functional::FinalStruct
  # @see http://www.ruby-doc.org/stdlib-2.1.2/libdoc/ostruct/rdoc/OpenStruct.html
  #
  # @!macro thread_safe_immutable_object
  class ValueStruct < Synchronization::Object

    def initialize(attributes)
      raise ArgumentError.new('attributes must be given as a hash') unless attributes.respond_to?(:each_pair)
      super
      @attribute_hash = {}
      attributes.each_pair do |field, value|
        set_attribute(field, value)
      end
      @attribute_hash.freeze
      ensure_ivar_visibility!
      self.freeze
    end

    # Get the value of the given field.
    #
    # @param [Symbol] field the field to retrieve the value for
    # @return [Object] the value of the field is set else nil
    def get(field)
      @attribute_hash[field.to_sym]
    end
    alias_method :[], :get

    # Check the internal hash to unambiguously verify that the given
    # attribute has been set.
    #
    # @param [Symbol] field the field to get the value for
    # @return [Boolean] true if the field has been set else false
    def set?(field)
      @attribute_hash.has_key?(field.to_sym)
    end

    # Get the current value of the given field if already set else return the given
    # default value.
    #
    # @param [Symbol] field the field to get the value for
    # @param [Object] default the value to return if the field has not been set
    # @return [Object] the value of the given field else the given default value
    def fetch(field, default)
      @attribute_hash.fetch(field.to_sym, default)
    end

    # Calls the block once for each attribute, passing the key/value pair as parameters.
    # If no block is given, an enumerator is returned instead.
    #
    # @yieldparam [Symbol] field the struct field for the current iteration
    # @yieldparam [Object] value the value of the current field
    #
    # @return [Enumerable] when no block is given
    def each_pair
      return enum_for(:each_pair) unless block_given?
      @attribute_hash.each do |field, value|
        yield(field, value)
      end
    end

    # Converts the `ValueStruct` to a `Hash` with keys representing each attribute
    # (as symbols) and their corresponding values.
    # 
    # @return [Hash] a `Hash` representing this struct
    def to_h
      @attribute_hash.dup # dup removes the frozen flag
    end

    # Compares this object and other for equality. A `ValueStruct` is `eql?` to
    # other when other is a `ValueStruct` and the two objects have identical
    # fields and values.
    #
    # @param [Object] other the other record to compare for equality
    # @return [Boolean] true when equal else false
    def eql?(other)
      other.is_a?(self.class) && @attribute_hash == other.to_h
    end
    alias_method :==, :eql?

    # Describe the contents of this object in a string.
    #
    # @return [String] the string representation of this object
    #
    # @!visibility private
    def inspect
      state = @attribute_hash.to_s.gsub(/^{/, '').gsub(/}$/, '')
      "#<#{self.class} #{state}>"
    end
    alias_method :to_s, :inspect

    protected

    # Set the value of the give field to the given value.
    #
    # @param [Symbol] field the field to set the value for
    # @param [Object] value the value to set the field to
    # @return [Object] the final value of the given field
    #
    # @!visibility private
    def set_attribute(field, value)
      @attribute_hash[field.to_sym] = value
    end

    # Check the method name and args for signatures matching potential
    # final predicate methods. If the signature matches call the appropriate
    # method
    #
    # @param [Symbol] symbol the name of the called function
    # @param [Array] args zero or more arguments
    # @return [Object] the result of the proxied method or the `super` call
    #
    # @!visibility private
    def method_missing(symbol, *args)
      if args.length == 0 && (match = /([^\?]+)\?$/.match(symbol))
        set?(match[1])
      elsif args.length == 0 && set?(symbol)
        get(symbol)
      else
        super
      end
    end
  end
end


================================================
FILE: lib/functional/version.rb
================================================
module Functional

  # The current gem version.
  VERSION = '1.3.0'
end


================================================
FILE: lib/functional.rb
================================================
require 'functional/delay'
require 'functional/either'
require 'functional/final_struct'
require 'functional/final_var'
require 'functional/memo'
require 'functional/option'
require 'functional/pattern_matching'
require 'functional/protocol'
require 'functional/protocol_info'
require 'functional/record'
require 'functional/tuple'
require 'functional/type_check'
require 'functional/union'
require 'functional/value_struct'
require 'functional/version'

Functional::SpecifyProtocol(:Disposition) do
  instance_method :value, 0
  instance_method :value?, 0
  instance_method :reason, 0
  instance_method :reason?, 0
  instance_method :fulfilled?, 0
  instance_method :rejected?, 0
end

# Erlang, Clojure, and Go inspired functional programming tools to Ruby.
module Functional

  # Infinity
  Infinity = 1/0.0

  # Not a number
  NaN = 0/0.0
end


================================================
FILE: spec/.gitignore
================================================


================================================
FILE: spec/functional/abstract_struct_shared.rb
================================================
shared_examples :abstract_struct do

  specify { Functional::Protocol::Satisfy! struct_class, :Struct }

  let(:other_struct) do
    Class.new do
      include Functional::AbstractStruct
      self.fields = [:foo, :bar, :baz].freeze
      self.datatype = :other_struct
    end
  end

  context 'field collection' do

    it 'contains all possible fields' do
      expected_fields.each do |field|
        expect(struct_class.fields).to include(field)
      end
    end

    it 'is frozen' do
      expect(struct_class.fields).to be_frozen
    end

    it 'does not overwrite fields for other structs' do
      expect(struct_class.fields).to_not eq other_struct.fields
    end

    it 'is the same when called on the class and on an object' do
      expect(struct_class.fields).to eq struct_object.fields
    end
  end

  context 'readers' do

    specify '#values returns all values in an array' do
      expect(struct_object.values).to eq expected_values
    end

    specify '#values is frozen' do
      expect(struct_object.values).to be_frozen
    end

    specify 'exist for each field' do
      expected_fields.each do |field|
        expect(struct_object).to respond_to(field)
        expect(struct_object.method(field).arity).to eq 0
      end
    end

    specify 'return the appropriate value all fields' do
      expected_fields.each_with_index do |field, i|
        expect(struct_object.send(field)).to eq expected_values[i]
      end
    end
  end

  context 'enumeration' do

    specify '#each_pair with a block iterates over all fields and values' do
      fields = []
      values = []

      struct_object.each_pair do |field, value|
        fields << field
        values << value
      end

      expect(fields).to eq struct_object.fields
      expect(values).to eq struct_object.values
    end

    specify '#each_pair without a block returns an Enumerable' do
      expect(struct_object.each_pair).to be_a Enumerable
    end

    specify '#each with a block iterates over all values' do
      values = []

      struct_object.each do |value|
        values << value
      end

      expect(values).to eq struct_object.values
    end

    specify '#each without a block returns an Enumerable' do
      expect(struct_object.each).to be_a Enumerable
    end
  end

  context 'reflection' do

    specify 'always creates frozen objects' do
      expect(struct_object).to be_frozen
    end

    specify 'asserts equality for two structs of the same class with equal values' do
      other = struct_object.dup

      expect(struct_object).to eq other
      expect(struct_object).to eql other
    end

    specify 'rejects equality for two structs of different classes' do
      other = Struct.new(*expected_fields).new(*expected_values)

      expect(struct_object).to_not eq other
      expect(struct_object).to_not eql other
    end

    specify 'rejects equality for two structs of the same class with different values' do
      expect(struct_object).to_not eq other_object
      expect(struct_object).to_not eql other_struct
    end

    specify '#to_h returns a Hash with all field/value pairs' do
      hsh = struct_object.to_h

      expect(hsh.keys).to eq struct_object.fields
      expect(hsh.values).to eq struct_object.values
    end

    specify '#inspect result is enclosed in brackets' do
      expect(struct_object.inspect).to match(/^#</)
      expect(struct_object.inspect).to match(/>$/)
    end

    specify '#inspect result has lowercase class name as first element' do
      struct = described_class.to_s.split('::').last.downcase
      expect(struct_object.inspect).to match(/^#<#{struct} /)
    end

    specify '#inspect includes all field/value pairs' do
      struct_object.fields.each_with_index do |field, i|
        value_regex = "\"?#{struct_object.values[i]}\"?"
        expect(struct_object.inspect).to match(/:#{field}=>#{value_regex}/)
      end
    end

    specify '#inspect is aliased as #to_s' do
      expect(struct_object.inspect).to eq struct_object.to_s
    end

    specify '#length returns the number of fields' do
      expect(struct_object.length).to eq struct_class.fields.length
      expect(struct_object.length).to eq expected_fields.length
    end

    specify 'aliases #length as #size' do
      expect(struct_object.length).to eq struct_object.size
    end
  end
end


================================================
FILE: spec/functional/complex_pattern_matching_spec.rb
================================================
require 'ostruct'

class Bar
  def greet
    return 'Hello, World!'
  end
end

class Foo < Bar
  include Functional::PatternMatching

  attr_accessor :name

  defn(:initialize) { @name = 'baz' }
  defn(:initialize, _) {|name| @name = name.to_s }

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

  defn(:greet, :male, _) { |name|
    "Hello, Mr. #{name}!"
  }
  defn(:greet, :female, _) { |name|
    "Hello, Ms. #{name}!"
  }
  defn(:greet, nil, _) { |name|
    "Goodbye, #{name}!"
  }
  defn(:greet, _, _) { |_, name|
    "Hello, #{name}!"
  }

  defn(:hashable, _, {foo: :bar}, _) { |_, opts, _|
    :foo_bar
  }
  defn(:hashable, _, {foo: _, bar: _}, _) { |_, f, b, _|
    [f, b]
  }
  defn(:hashable, _, {foo: _}, _) { |_, f, _|
    f
  }
  defn(:hashable, _, {}, _) { |_,_,_|
    :empty
  }
  defn(:hashable, _, _, _) { |_, _, _|
    :unbound
  }

  defn(:options, _) { |opts|
    opts
  }

  defn(:recurse) {
    'w00t!'
  }
  defn(:recurse, :match) {
    recurse()
  }
  defn(:recurse, :super) {
    greet()
  }
  defn(:recurse, :instance) {
    @name
  }
  defn(:recurse, _) { |arg|
    arg
  }

  defn(:concat, Integer, Integer) { |first, second|
    first + second
  }
  defn(:concat, Integer, String) { |first, second|
    "#{first} #{second}"
  }
  defn(:concat, String, String) { |first, second|
    first + second
  }
  defn(:concat, Integer, UNBOUND) { |first, second|
    first + second.to_i
  }

  defn(:all, :one, ALL) { |*args|
    args
  }
  defn(:all, :one, Integer, ALL) { |int, *args|
    [int, args]
  }
  defn(:all, 1, _, ALL) { |var, *args|
    [var, args]
  }
  defn(:all, ALL) { |*args|
    args
  }

  defn(:old_enough, _){ |_| true }.when{|x| x >= 16 }
  defn(:old_enough, _){ |_| false }

  defn(:right_age, _) { |_|
    true
  }.when{|x| x >= 16 && x <= 104 }

  defn(:right_age, _) { |_|
    false
  }

  defn(:wrong_age, _) { |_|
    true
  }.when{|x| x < 16 || x > 104 }

  defn(:wrong_age, _) { |_|
    false
  }
  end

class Baz < Foo
  def boom_boom_room
    'zoom zoom zoom'
  end
  def who(first, last)
    [first, last].join(' ')
  end
end

class Fizzbuzz < Baz
  include Functional::PatternMatching
  defn(:who, Integer) { |count|
    (1..count).each.reduce(:+)
  }
  defn(:who) { 0 }
end

describe 'complex pattern matching' do

  let(:name) { 'Pattern Matcher' }
  subject { Foo.new(name) }

  specify { expect(subject.greet).to eq 'Hello, World!' }

  specify { expect(subject.greet('Jerry')).to eq 'Hello, Jerry!' }

  specify { expect(subject.greet(:male, 'Jerry')).to eq 'Hello, Mr. Jerry!' }
  specify { expect(subject.greet(:female, 'Jeri')).to eq 'Hello, Ms. Jeri!' }
  specify { expect(subject.greet(:unknown, 'Jerry')).to eq 'Hello, Jerry!' }
  specify { expect(subject.greet(nil, 'Jerry')).to eq 'Goodbye, Jerry!' }

  # FIXME: This thing is failing because it can't match args that it got
  # and calling super, which can't handle it also and fail with ArgumentError
  # because super is usual ruby method, can't say what behavior here is
  # prefered (keep original ruby, or raise no method error somehow)
  # specify {
  #   expect { Foo.new.greet(1,2,3,4,5,6,7) }.to raise_error(NoMethodError)
  # }

  specify { expect(subject.options(bar: :baz, one: 1, many: 2)).to eq({bar: :baz, one: 1, many: 2}) }

  specify { expect(subject.hashable(:male, {foo: :bar}, :female)).to eq :foo_bar }
  specify { expect(subject.hashable(:male, {foo: :baz}, :female)).to eq :baz }
  specify { expect(subject.hashable(:male, {foo: 1, bar: 2}, :female)).to eq [1, 2] }
  specify { expect(subject.hashable(:male, {foo: 1, baz: 2}, :female)).to eq 1 }
  specify { expect(subject.hashable(:male, {bar: :baz}, :female)).to eq :unbound }
  specify { expect(subject.hashable(:male, {}, :female)).to eq :empty }

  specify { expect(subject.recurse).to eq 'w00t!' }
  specify { expect(subject.recurse(:match)).to eq 'w00t!' }
  specify { expect(subject.recurse(:super)).to eq 'Hello, World!' }
  specify { expect(subject.recurse(:instance)).to eq name }
  specify { expect(subject.recurse(:foo)).to eq :foo }

  specify { expect(subject.concat(1, 1)).to eq 2 }
  specify { expect(subject.concat(1, 'shoe')).to eq '1 shoe' }
  specify { expect(subject.concat('shoe', 'fly')).to eq 'shoefly' }
  specify { expect(subject.concat(1, 2.9)).to eq 3 }

  specify { expect(subject.all(:one, 'a', 'bee', :see)).to eq(['a', 'bee', :see]) }
  specify { expect(subject.all(:one, 1, 'bee', :see)).to eq([1, 'bee', :see]) }
  specify { expect(subject.all(1, 'a', 'bee', :see)).to eq(['a', ['bee', :see]]) }
  specify { expect(subject.all('a', 'bee', :see)).to eq(['a', 'bee', :see]) }
  specify { expect { subject.all }.to raise_error(NoMethodError) }

  specify { expect(subject.old_enough(20)).to be true }
  specify { expect(subject.old_enough(10)).to be false }

  specify { expect(subject.right_age(20)).to be true }
  specify { expect(subject.right_age(10)).to be false }
  specify { expect(subject.right_age(110)).to be false }

  specify { expect(subject.wrong_age(20)).to be false }
  specify { expect(subject.wrong_age(10)).to be true }
  specify { expect(subject.wrong_age(110)).to be true }

  context 'inheritance' do

    specify { expect(Fizzbuzz.new.greet(:male, 'Jerry')).to eq 'Hello, Mr. Jerry!' }
    specify { expect(Fizzbuzz.new.greet(:female, 'Jeri')).to eq 'Hello, Ms. Jeri!' }
    specify { expect(Fizzbuzz.new.greet(:unknown, 'Jerry')).to eq 'Hello, Jerry!' }
    specify { expect(Fizzbuzz.new.greet(nil, 'Jerry')).to eq 'Goodbye, Jerry!' }

    specify { expect(Fizzbuzz.new.who(5)).to eq 15 }
    specify { expect(Fizzbuzz.new.who()).to eq 0 }
    # FIXME: same issue with Foo's super here
    # specify {
    #   expect {
    #     Fizzbuzz.new.who('Jerry', 'secret middle name', "D'Antonio")
    #   }.to raise_error(NoMethodError)
    # }

    specify { expect(Fizzbuzz.new.boom_boom_room).to eq 'zoom zoom zoom' }
  end
end


================================================
FILE: spec/functional/delay_spec.rb
================================================
module Functional

  describe Delay do

    let!(:fulfilled_value) { 10 }
    let!(:rejected_reason) { StandardError.new('mojo jojo') }

    let(:pending_subject) do
      Delay.new{ fulfilled_value }
    end

    let(:fulfilled_subject) do
      delay = Delay.new{ fulfilled_value }
      delay.tap{ delay.value }
    end

    let(:rejected_subject) do
      delay = Delay.new{ raise rejected_reason }
      delay.tap{ delay.value }
    end

    specify{ Functional::Protocol::Satisfy! Delay, :Disposition }

    context '#initialize' do

      it 'sets the state to :pending' do
        expect(Delay.new{ nil }.state).to eq :pending
        expect(Delay.new{ nil }).to be_pending
      end

      it 'raises an exception when no block given' do
        expect {
          Delay.new
        }.to raise_error(ArgumentError)
      end
    end

    context '#state' do

      it 'is :pending when first created' do
        f = pending_subject
        expect(f.state).to eq(:pending)
        expect(f).to be_pending
      end

      it 'is :fulfilled when the handler completes' do
        f = fulfilled_subject
        expect(f.state).to eq(:fulfilled)
        expect(f).to be_fulfilled
      end

      it 'is :rejected when the handler raises an exception' do
        f = rejected_subject
        expect(f.state).to eq(:rejected)
        expect(f).to be_rejected
      end
    end

    context '#value' do

      let(:task){ proc{ nil } }

      it 'blocks the caller when :pending and timeout is nil' do
        f = pending_subject
        expect(f.value).to be_truthy
        expect(f).to be_fulfilled
      end

      it 'is nil when :rejected' do
        expected = rejected_subject.value
        expect(expected).to be_nil
      end

      it 'is set to the return value of the block when :fulfilled' do
        expected = fulfilled_subject.value
        expect(expected).to eq fulfilled_value
      end

      it 'does not call the block before #value is called' do
        expect(task).not_to receive(:call).with(any_args)
        Delay.new(&task)
      end

      it 'calls the block when #value is called' do
        expect(task).to receive(:call).once.with(any_args).and_return(nil)
        Delay.new(&task).value
      end

      it 'only calls the block once no matter how often #value is called' do
        expect(task).to receive(:call).once.with(any_args).and_return(nil)
        delay = Delay.new(&task)
        5.times{ delay.value }
      end
    end

    context '#reason' do

      it 'is nil when :pending' do
        expect(pending_subject.reason).to be_nil
      end

      it 'is nil when :fulfilled' do
        expect(fulfilled_subject.reason).to be_nil
      end

      it 'is set to error object of the exception when :rejected' do
        expect(rejected_subject.reason).to be_a(Exception)
        expect(rejected_subject.reason.to_s).to match(/#{rejected_reason}/)
      end
    end

    context 'predicates' do

      specify '#value? returns true when :fulfilled' do
        expect(pending_subject).to_not be_value
        expect(fulfilled_subject).to be_value
        expect(rejected_subject).to_not be_value
      end

      specify '#reason? returns true when :rejected' do
        expect(pending_subject).to_not be_reason
        expect(fulfilled_subject).to_not be_reason
        expect(rejected_subject).to be_reason
      end

      specify '#fulfilled? returns true when :fulfilled' do
        expect(pending_subject).to_not be_fulfilled
        expect(fulfilled_subject).to be_fulfilled
        expect(rejected_subject).to_not be_fulfilled
      end

      specify '#rejected? returns true when :rejected' do
        expect(pending_subject).to_not be_rejected
        expect(fulfilled_subject).to_not be_rejected
        expect(rejected_subject).to be_rejected
      end

      specify '#pending? returns true when :pending' do
        expect(pending_subject).to be_pending
        expect(fulfilled_subject).to_not be_pending
        expect(rejected_subject).to_not be_pending
      end
    end
  end
end


================================================
FILE: spec/functional/either_spec.rb
================================================
require_relative 'abstract_struct_shared'

module Functional

  describe Either do

    let!(:value){ 42 }
    let!(:reason){ StandardError.new }

    let!(:expected_fields){ [:left, :right] }
    let!(:expected_values){ [value, nil] }

    let(:struct_class) { Either }
    let(:struct_object) { Either.left(value) }
    let(:other_object) { Either.left(Object.new) }

    let(:left_subject){ Either.left(reason) }
    let(:right_subject){ Either.right(value) }

    it_should_behave_like :abstract_struct

    specify{ Functional::Protocol::Satisfy! Either, :Either }
    specify{ Functional::Protocol::Satisfy! Either, :Disposition }

    context 'initialization' do

      it 'cannot be constructed directly' do
        expect {
          Either.new
        }.to raise_error(NameError)
      end

      it 'sets the left value when constructed by #left' do
        expect(Either.left(value).left).to eq value
      end

      it 'sets the right value when constructed by #right' do
        expect(Either.right(value).right).to eq value
      end

      it 'freezes the new object' do
        expect(Either.left(:foo)).to be_frozen
        expect(Either.right(:foo)).to be_frozen
      end

      it 'aliases #left to #reason' do
        expect(Either.reason(value).left).to eq value
      end

      it 'aliases #right to #value' do
        expect(Either.value(value).right).to eq value
      end

      context '#error' do

        it 'sets left to a StandardError with backtrace when no arguments given' do
          either = Either.error
          expect(either.left).to be_a StandardError
          expect(either.left.message).to_not be nil
          expect(either.left.backtrace).to_not be_empty
        end

        it 'sets left to a StandardError with the given message' do
          message = 'custom error message'
          either = Either.error(message)
          expect(either.left).to be_a StandardError
          expect(either.left.message).to eq message
          expect(either.left.backtrace).to_not be_empty
        end

        it 'sets left to an object of the given class with the given message' do
          message = 'custom error message'
          error_class = ArgumentError
          either = Either.error(message, error_class)
          expect(either.left).to be_a error_class
          expect(either.left.message).to eq message
          expect(either.left.backtrace).to_not be_empty
        end
      end
    end

    context 'state' do

      specify '#left? returns true when the left value is set' do
        expect(left_subject).to be_left
      end

      specify '#left? returns false when the right value is set' do
        expect(right_subject).to_not be_left
      end

      specify '#right? returns true when the right value is set' do
        expect(right_subject).to be_right
      end

      specify '#right? returns false when the left value is set' do
        expect(left_subject).to_not be_right
      end

      specify '#left returns the left value when left is set' do
        expect(left_subject.left).to eq reason
      end

      specify '#left returns nil when right is set' do
        expect(right_subject.left).to be_nil
      end

      specify '#right returns the right value when right is set' do
        expect(right_subject.right).to eq value
      end

      specify '#right returns nil when left is set' do
        expect(left_subject.right).to be_nil
      end

      specify 'aliases #left? as #reason?' do
        expect(left_subject.reason?).to be true
      end

      specify 'aliases #right? as #value?' do
        expect(right_subject.value?).to be true
      end

      specify 'aliases #left as #reason' do
        expect(left_subject.reason).to eq reason
        expect(right_subject.reason).to be_nil
      end

      specify 'aliases #right as #value' do
        expect(right_subject.value).to eq value
        expect(left_subject.value).to be_nil
      end
    end

    context '#swap' do

      it 'converts a left projection into a right projection' do
        subject = Either.left(:foo)
        swapped = subject.swap
        expect(swapped).to be_right
        expect(swapped.left).to be_nil
        expect(swapped.right).to eq :foo
      end

      it 'converts a right projection into a left projection' do
        subject = Either.right(:foo)
        swapped = subject.swap
        expect(swapped).to be_left
        expect(swapped.right).to be_nil
        expect(swapped.left).to eq :foo
      end
    end

    context '#either' do

      it 'passes the left value to the left proc when left' do
        expected = nil
        subject = Either.left(100)
        subject.either(
          ->(left) { expected = left },
          ->(right) { expected = -1 }
        )
        expect(expected).to eq 100
      end

      it 'returns the value of the left proc when left' do
        subject = Either.left(100)
        expect(
          subject.either(
            ->(left) { left * 2 },
            ->(right) { nil }
          )
        ).to eq 200
      end

      it 'passes the right value to the right proc when right' do
        expected = nil
        subject = Either.right(100)
        subject.either(
          ->(right) { expected = -1 },
          ->(right) { expected = right }
        )
        expect(expected).to eq 100
      end

      it 'returns the value of the right proc when right' do
        subject = Either.right(100)
        expect(
          subject.either(
            ->(right) { nil },
            ->(right) { right * 2 }
          )
        ).to eq 200
      end
    end

    context '#iff' do

      it 'returns a lefty with the given left value when the boolean is true' do
        subject = Either.iff(:foo, :bar, true)
        expect(subject).to be_left
        expect(subject.left).to eq :foo
      end

      it 'returns a righty with the given right value when the boolean is false' do
        subject = Either.iff(:foo, :bar, false)
        expect(subject).to be_right
        expect(subject.right).to eq :bar
      end

      it 'returns a lefty with the given left value when the block is truthy' do
        subject = Either.iff(:foo, :bar){ :baz }
        expect(subject).to be_left
        expect(subject.left).to eq :foo
      end

      it 'returns a righty with the given right value when the block is false' do
        subject = Either.iff(:foo, :bar){ false }
        expect(subject).to be_right
        expect(subject.right).to eq :bar
      end

      it 'returns a righty with the given right value when the block is nil' do
        subject = Either.iff(:foo, :bar){ nil }
        expect(subject).to be_right
        expect(subject.right).to eq :bar
      end

      it 'raises an exception when both a boolean and a block are given' do
        expect {
          subject = Either.iff(:foo, :bar, true){ nil }
        }.to raise_error(ArgumentError)
      end
    end
  end
end


================================================
FILE: spec/functional/final_struct_spec.rb
================================================
require 'ostruct'

module Functional

  describe FinalStruct do

    context 'instanciation' do

      specify 'with no args defines no fields' do
        subject = FinalStruct.new
        expect(subject.to_h).to be_empty
      end

      specify 'with a hash sets fields using has values' do
        subject = FinalStruct.new(foo: 1, 'bar' => :two, baz: 'three')
        expect(subject.foo).to eq 1
        expect(subject.bar).to eq :two
        expect(subject.baz).to eq 'three'
      end

      specify 'with a hash creates true predicates for has keys' do
        subject = FinalStruct.new(foo: 1, 'bar' => :two, baz: 'three')
        expect(subject.foo?).to be true
        expect(subject.bar?).to be true
        expect(subject.baz?).to be true
      end

      specify 'can be created from any object that responds to #to_h' do
        clazz = Class.new do
          def to_h; {answer: 42, harmless: 'mostly'}; end
        end
        struct = clazz.new
        subject = FinalStruct.new(struct)
        expect(subject.answer).to eq 42
        expect(subject.harmless).to eq 'mostly'
      end

      specify 'raises an exception if given a non-hash argument' do
        expect {
          FinalStruct.new(:bogus)
        }.to raise_error(ArgumentError)
      end
    end

    context 'set fields' do

      subject do
        struct = FinalStruct.new
        struct.foo = 42
        struct.bar = "Don't Panic"
        struct
      end

      specify 'have a reader which returns the value' do
        expect(subject.foo).to eq 42
        expect(subject.bar).to eq "Don't Panic"
      end

      specify 'have a predicate which returns true' do
        expect(subject.foo?).to be true
        expect(subject.bar?).to be true
      end

      specify 'raise an exception when written to again' do
        expect {subject.foo = 0}.to raise_error(Functional::FinalityError)
        expect {subject.bar = 0}.to raise_error(Functional::FinalityError)
      end
    end

    context 'unset fields' do

      subject { FinalStruct.new }

      specify 'have a magic reader that always returns nil' do
        expect(subject.foo).to be nil
        expect(subject.bar).to be nil
        expect(subject.baz).to be nil
      end

      specify 'have a magic predicate that always returns false' do
        expect(subject.foo?).to be false
        expect(subject.bar?).to be false
        expect(subject.baz?).to be false
      end

      specify 'have a magic writer that sets the field' do
        expect(subject.foo = 42).to eq 42
        expect(subject.bar = :towel).to eq :towel
        expect(subject.baz = "Don't Panic").to eq "Don't Panic"
      end
    end

    context 'accessors' do

      let!(:field_value_pairs) { {foo: 1, bar: :two, baz: 'three'} }

      subject { FinalStruct.new(field_value_pairs) }

      specify '#get returns the value of a set field' do
        expect(subject.get(:foo)).to eq 1
      end

      specify '#get returns nil for an unset field' do
        expect(subject.get(:bogus)).to be nil
      end

      specify '#[] is an alias for #get' do
        expect(subject[:foo]).to eq 1
        expect(subject[:bogus]).to be nil
      end

      specify '#set sets the value of an unset field' do
        subject.set(:harmless, 'mostly')
        expect(subject.harmless).to eq 'mostly'
        expect(subject.harmless?).to be true
      end

      specify '#set raises an exception if the field has already been set' do
        subject.set(:harmless, 'mostly')
        expect {
          subject.set(:harmless, 'extremely')
        }.to raise_error(Functional::FinalityError)
      end

      specify '#[]= is an alias for set' do
        subject[:harmless] = 'mostly'
        expect(subject.harmless).to eq 'mostly'
        expect {
          subject[:harmless] = 'extremely'
        }.to raise_error(Functional::FinalityError)
      end

      specify '#set? returns false for an unset field' do
        expect(subject.set?(:harmless)).to be false
      end

      specify '#set? returns true for a field that has been set' do
        subject.set(:harmless, 'mostly')
        expect(subject.set?(:harmless)).to be true
      end

      specify '#get_or_set returns the value of a set field' do
        subject.answer = 42
        expect(subject.get_or_set(:answer, 100)).to eq 42
      end

      specify '#get_or_set sets the value of an unset field' do
        subject.get_or_set(:answer, 42)
        expect(subject.answer).to eq 42
        expect(subject.answer?).to be true
      end

      specify '#get_or_set returns the value of a newly set field' do
        expect(subject.get_or_set(:answer, 42)).to eq 42
      end

      specify '#fetch gets the value of a set field' do
        subject.harmless = 'mostly'
        expect(subject.fetch(:harmless, 'extremely')).to eq 'mostly'
      end

      specify '#fetch returns the given value when the field is unset' do
        expect(subject.fetch(:harmless, 'extremely')).to eq 'extremely'
      end

      specify '#fetch does not set an unset field' do
        subject.fetch(:answer, 42)
        expect(subject.answer).to be_nil
        expect(subject.answer?).to be false
      end

      specify '#to_h returns the key/value pairs for all set values' do
        subject = FinalStruct.new(field_value_pairs)
        expect(subject.to_h).to eq field_value_pairs
      end

      specify '#to_h is updated when new fields are added' do
        subject = FinalStruct.new
        field_value_pairs.each_pair do |field, value|
          subject.set(field, value)
        end
        expect(subject.to_h).to eq field_value_pairs
      end

      specify '#each_pair returns an Enumerable when no block given' do
        subject = FinalStruct.new(field_value_pairs)
        expect(subject.each_pair).to be_a Enumerable
      end

      specify '#each_pair enumerates over each field/value pair' do
        subject = FinalStruct.new(field_value_pairs)
        result = {}

        subject.each_pair do |field, value|
          result[field] = value
        end

        expect(result).to eq field_value_pairs
      end
    end

    context 'reflection' do

      specify '#eql? returns true when both define the same fields with the same values' do
        first = FinalStruct.new(foo: 1, 'bar' => :two, baz: 'three')
        second = FinalStruct.new(foo: 1, 'bar' => :two, baz: 'three')

        expect(first.eql?(second)).to be true
        expect(first == second).to be true
      end

      specify '#eql? returns false when other has different fields defined' do
        first = FinalStruct.new(foo: 1, 'bar' => :two, baz: 'three')
        second = FinalStruct.new(foo: 1, 'bar' => :two)

        expect(first.eql?(second)).to be false
        expect(first == second).to be false
      end

      specify '#eql? returns false when other has different field values' do
        first = FinalStruct.new(foo: 1, 'bar' => :two, baz: 'three')
        second = FinalStruct.new(foo: 1, 'bar' => :two, baz: 3)

        expect(first.eql?(second)).to be false
        expect(first == second).to be false
      end

      specify '#eql? returns false when other is not a FinalStruct' do
        attributes = {answer: 42, harmless: 'mostly'}
        clazz = Class.new do
          def to_h; {answer: 42, harmless: 'mostly'}; end
        end
        other = clazz.new
        subject = FinalStruct.new(attributes)
        expect(subject.eql?(other)).to be false
        expect(subject == other).to be false
      end

      specify '#inspect begins with the class name' do
        subject = FinalStruct.new(foo: 1, 'bar' => :two, baz: 'three')
        expect(subject.inspect).to match(/^#<#{described_class}\s+/)
      end

      specify '#inspect includes all field/value pairs' do
        field_value_pairs = {foo: 1, 'bar' => :two, baz: 'three'}
        subject = FinalStruct.new(field_value_pairs)

        field_value_pairs.each do |field, value|
          expect(subject.inspect).to match(/:#{field}=>"?:?#{value}"?/)
        end
      end

      specify '#to_s returns the same value as #inspect' do
        subject = FinalStruct.new(foo: 1, 'bar' => :two, baz: 'three')
        expect(subject.to_s).to eq subject.inspect
      end

      specify '#method_missing raises an exception for methods with unrecognized signatures' do
        expect {
          subject.foo(1, 2, 3)
        }.to raise_error(NoMethodError)
      end
    end
  end
end


================================================
FILE: spec/functional/final_var_spec.rb
================================================
module Functional

  describe FinalVar do

    context 'instanciation' do

      it 'is unset when no arguments given' do
        expect(FinalVar.new).to_not be_set
      end

      it 'is set with the given argument' do
        expect(FinalVar.new(41)).to be_set
      end
    end

    context '#get' do

      subject { FinalVar.new }

      it 'returns nil when unset' do
        expect(subject.get).to be nil
      end

      it 'returns the value when set' do
        expect(FinalVar.new(42).get).to eq 42
      end

      it 'is aliased as #value' do
        expect(subject.value).to be nil
        subject.set(42)
        expect(subject.value).to eq 42
      end
    end

    context '#set' do

      subject { FinalVar.new }

      it 'sets the value when unset' do
        subject.set(42)
        expect(subject.get).to eq 42
      end

      it 'returns the new value when unset' do
        expect(subject.set(42)).to eq 42
      end

      it 'raises an exception when already set' do
        subject.set(42)
        expect {
          subject.set(42)
        }.to raise_error(Functional::FinalityError)
      end

      it 'is aliased as #value=' do
        subject.value = 42
        expect(subject.get).to eq 42
      end
    end

    context '#set?' do

      it 'returns false when unset' do
        expect(FinalVar.new).to_not be_set
      end

      it 'returns true when set' do
        expect(FinalVar.new(42)).to be_set
      end

      it 'is aliased as value?' do
        expect(FinalVar.new.value?).to be false
        expect(FinalVar.new(42).value?).to be true
      end
    end

    context '#get_or_set' do

      it 'sets the value when unset' do
        subject = FinalVar.new
        subject.get_or_set(42)
        expect(subject.get).to eq 42
      end

      it 'returns the new value when previously unset' do
        subject = FinalVar.new
        expect(subject.get_or_set(42)).to eq 42
      end

      it 'returns the current value when already set' do
        subject = FinalVar.new(100)
        expect(subject.get_or_set(42)).to eq 100
      end
    end

    context '#fetch' do

      it 'returns the given default value when unset' do
        subject = FinalVar.new
        expect(subject.fetch(42)).to eq 42
      end

      it 'does not change the current value when unset' do
        subject = FinalVar.new
        subject.fetch(42)
        expect(subject.get).to be nil
      end

      it 'returns the current value when already set' do
        subject = FinalVar.new(100)
        expect(subject.get_or_set(42)).to eq 100
      end
    end

    context 'reflection' do

      specify '#eql? returns false when unset' do
        expect(FinalVar.new.eql?(nil)).to be false
        expect(FinalVar.new.eql?(42)).to be false
        expect(FinalVar.new.eql?(FinalVar.new.value)).to be false
      end

      specify '#eql? returns false when set and the value does not match other' do
        subject = FinalVar.new(42)
        expect(subject.eql?(100)).to be false
      end

      specify '#eql? returns true when set and the value matches other' do
        subject = FinalVar.new(42)
        expect(subject.eql?(42)).to be true
      end

      specify '#eql? returns true when set and other is a FinalVar with the same value' do
        subject = FinalVar.new(42)
        other = FinalVar.new(42)
        expect(subject.eql?(other)).to be true
      end

      specify 'aliases #== as #eql?' do
        expect(FinalVar.new == nil).to be false
        expect(FinalVar.new == 42).to be false
        expect(FinalVar.new == FinalVar.new).to be false
        expect(FinalVar.new(42) == 42).to be true
        expect(FinalVar.new(42) == FinalVar.new(42)).to be true
      end

      specify '#inspect includes the word "value" and the value when set' do
        subject = FinalVar.new(42)
        expect(subject.inspect).to match(/value\s?=\s?42\s*>$/)
      end

      specify '#inspect include the word "unset" when unset' do
        subject = FinalVar.new
        expect(subject.inspect).to match(/unset\s*>$/i)
      end

      specify '#to_s returns nil as a string when unset' do
        expect(FinalVar.new.to_s).to eq nil.to_s
      end

      specify '#to_s returns the value as a string when set' do
        expect(FinalVar.new(42).to_s).to eq 42.to_s
        expect(FinalVar.new('42').to_s).to eq '42'
      end
    end
  end
end


================================================
FILE: spec/functional/memo_spec.rb
================================================
module Functional

  describe Memo do

    def create_new_memo_class
      Class.new do
        include Functional::Memo

        class << self
          attr_accessor :count
        end

        self.count = 0

        def self.add(a, b)
          self.count += 1
          a + b
        end
        memoize :add

        def self.increment(n)
          self.count += 1
        end

        def self.exception(ex = StandardError)
          raise ex
        end
      end
    end

    subject{ create_new_memo_class }

    context 'specification' do

      it 'raises an exception when the method is not defined' do
        expect {
          subject.memoize(:bogus)
        }.to raise_error(NameError)
      end

      it 'raises an exception when the given method has already been memoized' do
        expect{
          subject.memoize(:add)
        }.to raise_error(ArgumentError)
      end

      it 'allocates a different cache for each class/module' do
        class_1 = create_new_memo_class
        class_2 = create_new_memo_class

        10.times do
          class_1.add(0, 0)
          class_2.add(0, 0)
        end

        expect(class_1.count).to eq 1
        expect(class_2.count).to eq 1
      end

      it 'works when included in a class' do
        subject = Class.new do
          include Functional::Memo
          class << self
            attr_accessor :count
          end
          self.count = 0
          def self.foo
            self.count += 1
          end
          memoize :foo
        end

        10.times{ subject.foo }
        expect(subject.count).to eq 1
      end

      it 'works when included in a module' do
        subject = Module.new do
          include Functional::Memo
          class << self
            attr_accessor :count
          end
          self.count = 0
          def self.foo
            self.count += 1
          end
          memoize :foo
        end

        10.times{ subject.foo }
        expect(subject.count).to eq 1
      end

      it 'works when extended by a module' do
        subject = Module.new do
          extend Functional::Memo
          class << self
            attr_accessor :count
          end
          self.count = 0
          def self.foo
            self.count += 1
          end
          memoize :foo
        end

        10.times{ subject.foo }
        expect(subject.count).to eq 1
      end
    end

    context 'caching behavior' do

      it 'calls the real method on first instance of given args' do
        subject.add(1, 2)
        expect(subject.count).to eq 1
      end

      it 'calls the real method on first instance of given args' do
        subject.add(1, 2)
        expect(subject.count).to eq 1
      end

      it 'uses the memo on second instance of given args' do
        5.times { subject.add(1, 2) }
        expect(subject.count).to eq 1
      end

      it 'calls the real method when given a block' do
        5.times { subject.add(1, 2){ nil } }
        expect(subject.count).to eq 5
      end

      it 'raises an exception when arity does not match' do
        expect {
          subject.add
        }.to raise_error(ArgumentError)
      end
    end

    context 'maximum cache size' do

      it 'raises an exception when given a non-positive :at_most' do
        expect {
          subject.memoize(:increment, at_most: -1)
        }.to raise_error(ArgumentError)
      end

      it 'sets no limit when :at_most not given' do
        subject.memoize(:increment)
        10000.times{|i| subject.increment(i) }
        expect(subject.count).to eq 10000
      end

      it 'calls the real method when the :at_most size is reached' do
        subject.memoize(:increment, at_most: 5)
        10000.times{|i| subject.increment(i % 10) }
        expect(subject.count).to eq 5005
      end
    end

    context 'thread safety' do

      let(:memoizer_factory){ Functional::Memo::ClassMethods.const_get(:Memoizer) }
      let(:memoizer){ memoizer_factory.new(:func, 0) }

      before(:each) do
        allow(memoizer_factory).to receive(:new).with(any_args).and_return(memoizer)
      end

      it 'locks a mutex whenever a memoized function is called' do
        expect(memoizer).to receive(:synchronize).exactly(:once).with(no_args)

        subject.memoize(:increment)
        subject.increment(0)
      end

      it 'unlocks the mutex whenever a memoized function is called' do
        expect(memoizer).to receive(:synchronize).exactly(:once).with(no_args)

        subject.memoize(:increment)
        subject.increment(0)
      end

      it 'unlocks the mutex when the method call raises an exception' do
        expect(memoizer).to receive(:synchronize).exactly(:once).with(no_args)

        subject.memoize(:exception)
        begin
          subject.exception
        rescue
          # suppress
        end
      end

      it 'uses different mutexes for different functions' do
        expect(memoizer_factory).to receive(:new).with(any_args).exactly(3).times.and_return(memoizer)
        # once for memoize(:add) in the definition
        subject.memoize(:increment)
        subject.memoize(:exception)
      end
    end
  end
end


================================================
FILE: spec/functional/option_spec.rb
================================================
require_relative 'abstract_struct_shared'
require 'securerandom'

module Functional

  describe Option do

    let!(:value){ 42 }

    let!(:expected_fields){ [:some] }
    let!(:expected_values){ [value] }

    let(:struct_class) { Option }
    let(:struct_object) { Option.some(value) }
    let(:other_object) { Option.some(Object.new) }

    let(:some_subject){ Option.some(value) }
    let(:none_subject){ Option.none }

    it_should_behave_like :abstract_struct

    specify{ Functional::Protocol::Satisfy! Option, :Option }
    specify{ Functional::Protocol::Satisfy! Option, :Disposition }

    let(:some_value){ SecureRandom.uuid }
    let(:other_value){ SecureRandom.uuid }

    context 'initialization' do

      it 'cannot be constructed directly' do
        expect {
          Option.new
        }.to raise_error(NameError)
      end

      it 'sets the value when constructed by #some' do
        expect(Option.some(value).some).to eq value
      end

      it 'sets the value to nil when constructed by #none' do
        expect(Option.none.some).to be_nil
      end

      it 'sets the reason to nil when constructed by #none' do
        expect(Option.none.reason).to be_nil
      end

      it 'sets the optional reason when constructed by #none' do
        reason = 'foobar'
        expect(Option.none(reason).reason).to eq reason
      end

      it 'freezes the new object' do
        expect(Option.some(:foo)).to be_frozen
        expect(Option.none).to be_frozen
      end
    end

    context 'state' do

      specify '#some? returns true when the some value is set' do
        expect(some_subject).to be_some
    
Download .txt
gitextract_u_5mpmcl/

├── .coveralls.yml
├── .gitignore
├── .rspec
├── .travis.yml
├── .yardopts
├── CHANGELOG.md
├── CODE_OF_CONDUCT.md
├── Gemfile
├── LICENSE
├── README.md
├── Rakefile
├── appveyor.yml
├── doc/
│   ├── memo.md
│   ├── memoize.rb
│   ├── pattern_matching.md
│   ├── protocol.md
│   └── record.md
├── functional_ruby.gemspec
├── lib/
│   ├── functional/
│   │   ├── abstract_struct.rb
│   │   ├── delay.rb
│   │   ├── either.rb
│   │   ├── final_struct.rb
│   │   ├── final_var.rb
│   │   ├── memo.rb
│   │   ├── method_signature.rb
│   │   ├── option.rb
│   │   ├── pattern_matching.rb
│   │   ├── protocol.rb
│   │   ├── protocol_info.rb
│   │   ├── record.rb
│   │   ├── synchronization.rb
│   │   ├── tuple.rb
│   │   ├── type_check.rb
│   │   ├── union.rb
│   │   ├── value_struct.rb
│   │   └── version.rb
│   └── functional.rb
├── spec/
│   ├── .gitignore
│   ├── functional/
│   │   ├── abstract_struct_shared.rb
│   │   ├── complex_pattern_matching_spec.rb
│   │   ├── delay_spec.rb
│   │   ├── either_spec.rb
│   │   ├── final_struct_spec.rb
│   │   ├── final_var_spec.rb
│   │   ├── memo_spec.rb
│   │   ├── option_spec.rb
│   │   ├── pattern_matching_spec.rb
│   │   ├── protocol_info_spec.rb
│   │   ├── protocol_spec.rb
│   │   ├── record_spec.rb
│   │   ├── tuple_spec.rb
│   │   ├── type_check_spec.rb
│   │   ├── union_spec.rb
│   │   └── value_struct_spec.rb
│   ├── spec_helper.rb
│   └── support/
│       └── .gitignore
└── tasks/
    ├── .gitignore
    ├── metrics.rake
    └── update_doc.rake
Download .txt
SYMBOL INDEX (339 symbols across 35 files)

FILE: doc/memoize.rb
  class Factors (line 6) | class Factors
    method sum_of (line 9) | def self.sum_of(number)
    method of (line 13) | def self.of(number)
    method factor? (line 17) | def self.factor?(number, potential)
    method perfect? (line 21) | def self.perfect?(number)
    method abundant? (line 25) | def self.abundant?(number)
    method deficient? (line 29) | def self.deficient?(number)
  function memory_usage (line 40) | def memory_usage
  function print_memory_usage (line 44) | def print_memory_usage
  function run_benchmark (line 49) | def run_benchmark(n = 10000)

FILE: lib/functional.rb
  type Functional (line 27) | module Functional

FILE: lib/functional/abstract_struct.rb
  type Functional (line 12) | module Functional
    type AbstractStruct (line 16) | module AbstractStruct
      function each (line 27) | def each
      function each_pair (line 41) | def each_pair
      function eql? (line 53) | def eql?(other)
      function inspect (line 64) | def inspect
      function length (line 73) | def length
      function fields (line 81) | def fields
      function to_h (line 88) | def to_h
      function set_data_hash (line 98) | def set_data_hash(data)
      function set_values_array (line 106) | def set_values_array(values)
      function define_class (line 121) | def self.define_class(parent, datatype, fields)
      function included (line 135) | def self.included(base)
      type ClassMethods (line 143) | module ClassMethods

FILE: lib/functional/delay.rb
  type Functional (line 3) | module Functional
    class Delay (line 30) | class Delay < Synchronization::Object
      method initialize (line 37) | def initialize(&block)
      method state (line 49) | def state
      method reason (line 58) | def reason
      method value (line 75) | def value
      method fulfilled? (line 81) | def fulfilled?
      method rejected? (line 88) | def rejected?
      method pending? (line 95) | def pending?
      method execute_task_once (line 107) | def execute_task_once

FILE: lib/functional/either.rb
  type Functional (line 12) | module Functional
    class Either (line 84) | class Either < Synchronization::Object
      method left (line 101) | def left(value)
      method right (line 110) | def right(value)
      method error (line 133) | def error(message = nil, clazz = StandardError)
      method left (line 143) | def left
      method right (line 151) | def right
      method left? (line 159) | def left?
      method right? (line 168) | def right?
      method swap (line 177) | def swap
      method either (line 190) | def either(lproc, rproc)
      method iff (line 204) | def self.iff(lvalue, rvalue, condition = NO_VALUE)
      method initialize (line 218) | def initialize(value, is_left)

FILE: lib/functional/final_struct.rb
  type Functional (line 4) | module Functional
    class FinalStruct (line 48) | class FinalStruct < Synchronization::Object
      method initialize (line 55) | def initialize(attributes = {})
      method get (line 72) | def get(field)
      method set (line 90) | def set(field, value)
      method set? (line 108) | def set?(field)
      method get_or_set (line 118) | def get_or_set(field, value)
      method fetch (line 128) | def fetch(field, default)
      method each_pair (line 139) | def each_pair
      method to_h (line 152) | def to_h
      method eql? (line 162) | def eql?(other)
      method inspect (line 172) | def inspect
      method ns_get_attribute (line 182) | def ns_get_attribute(field)
      method ns_set_attribute (line 188) | def ns_set_attribute(field, value)
      method ns_attribute_has_been_set? (line 194) | def ns_attribute_has_been_set?(field)
      method method_missing (line 208) | def method_missing(symbol, *args)

FILE: lib/functional/final_var.rb
  type Functional (line 3) | module Functional
    class FinalVar (line 44) | class FinalVar < Synchronization::Object
      method initialize (line 53) | def initialize(value = NO_VALUE)
      method get (line 61) | def get
      method set (line 71) | def set(value)
      method set? (line 85) | def set?
      method get_or_set (line 94) | def get_or_set(value)
      method fetch (line 108) | def fetch(default)
      method eql? (line 120) | def eql?(other)
      method inspect (line 136) | def inspect
      method to_s (line 150) | def to_s
      method has_been_set? (line 158) | def has_been_set?

FILE: lib/functional/memo.rb
  type Functional (line 3) | module Functional
    type Memo (line 18) | module Memo
      function extended (line 21) | def self.extended(base)
      function included (line 28) | def self.included(base)
      type ClassMethods (line 35) | module ClassMethods
        class Memoizer (line 38) | class Memoizer < Synchronization::Object
          method initialize (line 40) | def initialize(function, max_cache)
          method max_cache? (line 48) | def max_cache?
        function memoize (line 71) | def memoize(func, opts = {})
        function __define_memo_proxy__ (line 82) | def __define_memo_proxy__(func)
        function __proxy_memoized_method__ (line 91) | def __proxy_memoized_method__(func, *args, &block)

FILE: lib/functional/method_signature.rb
  type Functional (line 1) | module Functional
    type PatternMatching (line 3) | module PatternMatching
      type MethodSignature (line 9) | module MethodSignature
        function match? (line 15) | def match?(pattern, args)
        function valid_pattern? (line 33) | def valid_pattern?(args, pattern)
        function all_param_and_last_arg? (line 41) | def all_param_and_last_arg?(pattern, param, index)
        function arg_is_type_of_param? (line 49) | def arg_is_type_of_param?(param, arg)
        function hash_param_with_matching_arg? (line 57) | def hash_param_with_matching_arg?(param, arg)
        function param_matches_arg? (line 67) | def param_matches_arg?(param, arg)

FILE: lib/functional/option.rb
  type Functional (line 12) | module Functional
    class Option (line 21) | class Option < Synchronization::Object
      method none (line 41) | def none(reason = nil)
      method some (line 49) | def some(value)
      method some? (line 57) | def some?
      method none? (line 66) | def none?
      method some (line 75) | def some
      method length (line 85) | def length
      method and (line 106) | def and(other = NO_OPTION)
      method or (line 134) | def or(other = NO_OPTION)
      method else (line 158) | def else(other = NO_OPTION)
      method iff (line 180) | def self.iff(value, condition = NO_OPTION)
      method inspect (line 187) | def inspect
      method initialize (line 201) | def initialize(value, none, reason = nil)

FILE: lib/functional/pattern_matching.rb
  type Functional (line 3) | module Functional
    type PatternMatching (line 15) | module PatternMatching
      function initialize (line 30) | def initialize(function, clazz, pattern)
      function when (line 35) | def when(&block)
      function __unbound_args__ (line 50) | def __unbound_args__(match, args)
      function __pass_guard__? (line 68) | def __pass_guard__?(matcher, args)
      function __pattern_match__ (line 74) | def __pattern_match__(clazz, function, *args, &block)
      function included (line 83) | def self.included(base)
      type ClassMethods (line 90) | module ClassMethods
        function _ (line 93) | def _()
        function defn (line 98) | def defn(function, *args, &block)
        function __define_method_with_matching__ (line 125) | def __define_method_with_matching__(function)
        function __function_pattern_matches__ (line 147) | def __function_pattern_matches__
        function __register_pattern__ (line 152) | def __register_pattern__(function, *args, &block)
        function __pattern_arity__ (line 162) | def __pattern_arity__(pat)

FILE: lib/functional/protocol.rb
  type Functional (line 3) | module Functional
    function SpecifyProtocol (line 38) | def SpecifyProtocol(name, &block)
    type Protocol (line 60) | module Protocol
      function Satisfy? (line 72) | def Satisfy?(target, *protocols)
      function Satisfy! (line 87) | def Satisfy!(target, *protocols)
      function Specified? (line 100) | def Specified?(*protocols)
      function Specified! (line 115) | def Specified!(*protocols)
      function satisfies? (line 129) | def self.satisfies?(target, protocol)
      function unspecified (line 138) | def self.unspecified(*protocols)
      function error (line 151) | def self.error(target, message, *protocols)

FILE: lib/functional/protocol_info.rb
  type Functional (line 3) | module Functional
    class ProtocolInfo (line 9) | class ProtocolInfo < Synchronization::Object
      method initialize (line 22) | def initialize(name, &specification)
      method instance_methods (line 39) | def instance_methods
      method class_methods (line 47) | def class_methods
      method constants (line 54) | def constants
      method satisfies? (line 61) | def satisfies?(target)
      method satisfies_constants? (line 77) | def satisfies_constants?(target)
      method satisfies_instance_methods? (line 86) | def satisfies_instance_methods?(target)
      method satisfies_class_methods? (line 101) | def satisfies_class_methods?(target)
      method check_arity? (line 121) | def check_arity?(method, expected)
      method instance_method (line 133) | def instance_method(name, arity = nil)
      method class_method (line 142) | def class_method(name, arity = nil)
      method attr_reader (line 150) | def attr_reader(name)
      method attr_writer (line 157) | def attr_writer(name)
      method attr_accessor (line 164) | def attr_accessor(name)
      method class_attr_reader (line 172) | def class_attr_reader(name)
      method class_attr_writer (line 179) | def class_attr_writer(name)
      method class_attr_accessor (line 186) | def class_attr_accessor(name)
      method constant (line 194) | def constant(name)

FILE: lib/functional/record.rb
  type Functional (line 5) | module Functional
    type Record (line 25) | module Record
      function new (line 33) | def new(*fields, &block)
      class Restrictions (line 62) | class Restrictions
        method initialize (line 73) | def initialize(types = nil, &block)
        method mandatory (line 86) | def mandatory(*fields)
        method default (line 94) | def default(field, value)
        method clone_default (line 104) | def clone_default(field)
        method validate! (line 117) | def validate!(data)
        method validate_mandatory! (line 129) | def validate_mandatory!(data)
        method validate_types! (line 139) | def validate_types!(data)
        method uncloneable? (line 156) | def uncloneable?(object)
      function check_types! (line 166) | def check_types!(types)
      function build (line 179) | def build(name, fields, types, &block)
      function define_initializer (line 194) | def define_initializer(record)
      function define_reader (line 216) | def define_reader(record, field)

FILE: lib/functional/synchronization.rb
  type Functional (line 1) | module Functional
    type Synchronization (line 7) | module Synchronization
      class Object (line 14) | class Object
        method initialize (line 17) | def initialize(*args)
        method synchronize (line 23) | def synchronize
        method ensure_ivar_visibility! (line 28) | def ensure_ivar_visibility!
        method initialize (line 39) | def initialize(*args)
        method synchronize (line 45) | def synchronize(&block)
        method ensure_ivar_visibility! (line 50) | def ensure_ivar_visibility!
        method initialize (line 64) | def initialize(*args)
        method synchronize (line 72) | def synchronize
        method ensure_ivar_visibility! (line 81) | def ensure_ivar_visibility!
      class Object (line 36) | class Object
        method initialize (line 17) | def initialize(*args)
        method synchronize (line 23) | def synchronize
        method ensure_ivar_visibility! (line 28) | def ensure_ivar_visibility!
        method initialize (line 39) | def initialize(*args)
        method synchronize (line 45) | def synchronize(&block)
        method ensure_ivar_visibility! (line 50) | def ensure_ivar_visibility!
        method initialize (line 64) | def initialize(*args)
        method synchronize (line 72) | def synchronize
        method ensure_ivar_visibility! (line 81) | def ensure_ivar_visibility!
      class Object (line 61) | class Object
        method initialize (line 17) | def initialize(*args)
        method synchronize (line 23) | def synchronize
        method ensure_ivar_visibility! (line 28) | def ensure_ivar_visibility!
        method initialize (line 39) | def initialize(*args)
        method synchronize (line 45) | def synchronize(&block)
        method ensure_ivar_visibility! (line 50) | def ensure_ivar_visibility!
        method initialize (line 64) | def initialize(*args)
        method synchronize (line 72) | def synchronize
        method ensure_ivar_visibility! (line 81) | def ensure_ivar_visibility!

FILE: lib/functional/tuple.rb
  type Functional (line 3) | module Functional
    class Tuple (line 24) | class Tuple < Synchronization::Object
      method initialize (line 30) | def initialize(data = [])
      method at (line 45) | def at(index)
      method fetch (line 60) | def fetch(index, default)
      method length (line 71) | def length
      method intersect (line 82) | def intersect(other)
      method union (line 91) | def union(other)
      method concat (line 100) | def concat(other)
      method diff (line 109) | def diff(other)
      method repeat (line 120) | def repeat(multiple)
      method uniq (line 130) | def uniq
      method each (line 139) | def each
      method each_with_index (line 152) | def each_with_index
      method sequence (line 169) | def sequence
      method eql? (line 188) | def eql?(other)
      method empty? (line 196) | def empty?
      method first (line 203) | def first
      method rest (line 212) | def rest
      method to_a (line 225) | def to_a
      method inspect (line 235) | def inspect
      method to_s (line 245) | def to_s

FILE: lib/functional/type_check.rb
  type Functional (line 1) | module Functional
    type TypeCheck (line 6) | module TypeCheck
      function Type? (line 15) | def Type?(value, *types)
      function Type! (line 29) | def Type!(value, *types)
      function Match? (line 45) | def Match?(value, *types)
      function Match! (line 62) | def Match!(value, *types)
      function Child? (line 76) | def Child?(value, *types)
      function Child! (line 90) | def Child!(value, *types)
      function error (line 107) | def self.error(value, message, types)

FILE: lib/functional/union.rb
  type Functional (line 4) | module Functional
    type Union (line 56) | module Union
      function new (line 63) | def new(*fields)
      function build (line 75) | def build(fields)
      function define_properties (line 92) | def define_properties(union)
      function define_predicate (line 103) | def define_predicate(union, field)
      function define_reader (line 115) | def define_reader(union, field)
      function define_initializer (line 126) | def define_initializer(union)
      function define_factory (line 148) | def define_factory(union, field)

FILE: lib/functional/value_struct.rb
  type Functional (line 3) | module Functional
    class ValueStruct (line 28) | class ValueStruct < Synchronization::Object
      method initialize (line 30) | def initialize(attributes)
      method get (line 46) | def get(field)
      method set? (line 56) | def set?(field)
      method fetch (line 66) | def fetch(field, default)
      method each_pair (line 77) | def each_pair
      method to_h (line 88) | def to_h
      method eql? (line 98) | def eql?(other)
      method inspect (line 108) | def inspect
      method set_attribute (line 123) | def set_attribute(field, value)
      method method_missing (line 136) | def method_missing(symbol, *args)

FILE: lib/functional/version.rb
  type Functional (line 1) | module Functional

FILE: spec/functional/complex_pattern_matching_spec.rb
  class Bar (line 3) | class Bar
    method greet (line 4) | def greet
  class Foo (line 9) | class Foo < Bar
  class Baz (line 116) | class Baz < Foo
    method boom_boom_room (line 117) | def boom_boom_room
    method who (line 120) | def who(first, last)
  class Fizzbuzz (line 125) | class Fizzbuzz < Baz

FILE: spec/functional/delay_spec.rb
  type Functional (line 1) | module Functional

FILE: spec/functional/either_spec.rb
  type Functional (line 3) | module Functional

FILE: spec/functional/final_struct_spec.rb
  type Functional (line 3) | module Functional
    function to_h (line 30) | def to_h; {answer: 42, harmless: 'mostly'}; end
    function to_h (line 231) | def to_h; {answer: 42, harmless: 'mostly'}; end

FILE: spec/functional/final_var_spec.rb
  type Functional (line 1) | module Functional

FILE: spec/functional/memo_spec.rb
  type Functional (line 1) | module Functional
    function create_new_memo_class (line 5) | def create_new_memo_class
    function foo (line 67) | def self.foo
    function foo (line 84) | def self.foo
    function foo (line 101) | def self.foo

FILE: spec/functional/option_spec.rb
  type Functional (line 4) | module Functional

FILE: spec/functional/pattern_matching_spec.rb
  type Functional (line 3) | module Functional
    function new_clazz (line 7) | def new_clazz(&block)
    class Clazz (line 20) | class Clazz
    class UnmatchedCallTesterSuperclass (line 87) | class UnmatchedCallTesterSuperclass
      method foo (line 88) | def foo(bar)
    class UnmatchedCallTesterSubclass (line 93) | class UnmatchedCallTesterSubclass < UnmatchedCallTesterSuperclass
    class RecursiveCallTesterSuperclass (line 112) | class RecursiveCallTesterSuperclass
      method foo (line 113) | def foo(bar)
    class RecursiveCallTesterSubclass (line 118) | class RecursiveCallTesterSubclass < RecursiveCallTesterSuperclass
    function tst (line 420) | def tst; :test end

FILE: spec/functional/protocol_info_spec.rb
  type Functional (line 1) | module Functional
    function bar (line 139) | def bar(a, b, c=1, d=2, *args); nil; end
    function baz (line 140) | def self.baz(); nil; end
    function bar (line 153) | def bar(); nil; end
    function baz (line 154) | def self.baz(); nil; end
    function bar (line 167) | def bar(a,b,c); nil; end
    function baz (line 168) | def self.baz(a,b,c); nil; end
    function bar (line 181) | def bar(a, b=1); nil; end
    function baz (line 182) | def self.baz(a, b=1, c=2); nil; end
    function bar (line 210) | def bar(a, *args); nil; end
    function baz (line 211) | def self.baz(a, b, *args); nil; end
    function bar (line 224) | def bar(*args); nil; end
    function baz (line 225) | def self.baz(*args); nil; end
    function foo (line 241) | def foo() true; end
    function foo= (line 242) | def foo=(value) true; end
    function foo (line 261) | def self.foo() true; end
    function foo= (line 262) | def self.foo=(value) true; end
    function foo (line 292) | def foo(); nil; end
    function bar (line 293) | def bar(a, b, c); nil; end
    function baz (line 294) | def baz(a, b, *args); nil; end
    function foo (line 295) | def self.foo(); nil; end
    function bar (line 296) | def self.bar(a, b, c); nil; end
    function baz (line 297) | def self.baz(a, b, *args); nil; end
    function foo (line 314) | def foo(*args); nil; end
    function bar (line 315) | def bar(*args); nil; end
    function baz (line 316) | def baz(*args); nil; end
    function foo (line 317) | def self.foo(*args); nil; end
    function bar (line 318) | def self.bar(*args); nil; end
    function baz (line 319) | def self.baz(*args); nil; end
    function bar (line 331) | def bar(a, b, *args); nil; end
    function bar (line 343) | def self.bar(a, b, *args); nil; end
    function foo (line 355) | def foo() true; end
    function foo= (line 356) | def foo=() false; end
    function foo (line 360) | def foo(value) false; end
    function foo= (line 361) | def foo=(value) true; end
    function foo (line 374) | def self.foo() true; end
    function foo= (line 375) | def self.foo=() false; end
    function foo (line 379) | def self.foo(value) false; end
    function foo= (line 380) | def self.foo=(value) true; end
    function instance_method (line 404) | def instance_method() 42; end
    function class_method (line 410) | def class_method() 42; end
    function instance_method (line 425) | def instance_method() 42; end
    function class_method (line 431) | def class_method() 42; end

FILE: spec/functional/protocol_spec.rb
  function foo (line 52) | def foo(); nil; end
  function foo (line 78) | def foo(); nil; end
  function foo (line 93) | def foo(); nil; end
  function foo (line 108) | def foo(); nil; end
  function bar (line 109) | def self.bar(); nil; end
  function foo (line 124) | def foo(); nil; end
  function bar (line 125) | def self.bar(); nil; end
  function foo (line 142) | def foo(); nil; end
  function foo (line 169) | def foo(); nil; end
  function foo (line 193) | def foo(); nil; end
  function bar (line 194) | def self.bar(); nil; end
  function foo (line 209) | def foo(); nil; end
  function bar (line 210) | def self.bar(); nil; end

FILE: spec/functional/record_spec.rb
  type Functional (line 4) | module Functional
    function foo (line 203) | def foo() nil end
    function full_name (line 266) | def full_name
    function formal_name (line 270) | def formal_name

FILE: spec/functional/tuple_spec.rb
  type Functional (line 9) | module Functional
    function to_a (line 34) | def to_a() [:foo, :bar, :baz]; end
    function to_a (line 182) | def to_a() [2, 3, 4]; end
    function to_a (line 244) | def to_a() [2, 3, 4]; end
    function to_a (line 298) | def to_a() [4, 5, 6]; end
    function to_a (line 368) | def to_a() [3, 4, 5]; end
    function to_a (line 558) | def to_a() [1, 2, 3]; end

FILE: spec/functional/type_check_spec.rb
  type Functional (line 1) | module Functional

FILE: spec/functional/union_spec.rb
  type Functional (line 3) | module Functional

FILE: spec/functional/value_struct_spec.rb
  type Functional (line 3) | module Functional
    function each_pair (line 31) | def each_pair(&block)
    function to_h (line 168) | def to_h; {answer: 42, harmless: 'mostly'}; end
Condensed preview — 59 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (288K chars).
[
  {
    "path": ".coveralls.yml",
    "chars": 46,
    "preview": "repo_token: M3JnILwxCIYb4OjWvyxBJkib9xsAGdnek\n"
  },
  {
    "path": ".gitignore",
    "chars": 339,
    "preview": "Gemfile.lock\n.rspec-local\n*.gem\nlib/1.8\nlib/1.9\nlib/2.0\n.rvmrc\n.ruby-version\n.ruby-gemset\n.bundle/*\n.yardoc/*\nyardoc/*\nt"
  },
  {
    "path": ".rspec",
    "chars": 40,
    "preview": "--require spec_helper\n--format progress\n"
  },
  {
    "path": ".travis.yml",
    "chars": 485,
    "preview": "language: ruby\n\nrvm:\n  - 2.2.3\n  - 2.2.2\n  - 2.2.1\n  - 2.1.5\n  - 2.1.4\n  - 2.0.0\n  - ruby-head\n  - jruby-1.7.19\n  - jrub"
  },
  {
    "path": ".yardopts",
    "chars": 171,
    "preview": "--protected\n--no-private\n--embed-mixins\n--output-dir ./yardoc\n--markup markdown\n--title=Functional Ruby\n--template defau"
  },
  {
    "path": "CHANGELOG.md",
    "chars": 2373,
    "preview": "## Current Release v1.3.0 (October 4, 2015)\n\n* Pattern match now check arity of pattern and block\n* `PatternMatching::AL"
  },
  {
    "path": "CODE_OF_CONDUCT.md",
    "chars": 1981,
    "preview": "# Contributor Code of Conduct\n\nAs contributors and maintainers of this project, and in the interest of fostering an open"
  },
  {
    "path": "Gemfile",
    "chars": 462,
    "preview": "source 'https://rubygems.org'\n\ngemspec\n\ngroup :development do\n  gem 'rake', '~> 12.3.0'\nend\n\ngroup :testing do\n  gem 'rs"
  },
  {
    "path": "LICENSE",
    "chars": 1174,
    "preview": "Copyright (c) Jerry D'Antonio -- released under the MIT license.\n\nhttp://www.opensource.org/licenses/mit-license.php  \n\n"
  },
  {
    "path": "README.md",
    "chars": 7617,
    "preview": "# Functional Ruby\n[![Gem Version](https://badge.fury.io/rb/functional-ruby.svg)](http://badge.fury.io/rb/functional-ruby"
  },
  {
    "path": "Rakefile",
    "chars": 543,
    "preview": "$:.push File.join(File.dirname(__FILE__), 'lib')\n\nGEMSPEC = Gem::Specification.load('functional-ruby.gemspec')\n\nrequire "
  },
  {
    "path": "appveyor.yml",
    "chars": 460,
    "preview": "install:\n  - SET PATH=C:\\Ruby%ruby_version%\\bin;%PATH%\n  - SET PATH=C:\\MinGW\\bin;%PATH%\n  - SET RAKEOPT=-rdevkit\n  - rub"
  },
  {
    "path": "doc/memo.md",
    "chars": 6851,
    "preview": "# memoize\n\n###    Rationale\n\n   Many computational operations take a significant amount of time and/or use\n   an inordin"
  },
  {
    "path": "doc/memoize.rb",
    "chars": 1489,
    "preview": "#!/usr/bin/env ruby\n$LOAD_PATH << File.expand_path('../../lib', __FILE__)\n\nrequire 'functional'\n\nclass Factors\n  include"
  },
  {
    "path": "doc/pattern_matching.md",
    "chars": 12291,
    "preview": "###    Features\n\n   * Pattern matching for instance methods.\n   * Pattern matching for object constructors.\n   * Paramet"
  },
  {
    "path": "doc/protocol.md",
    "chars": 8491,
    "preview": "###    Rationale\n\n   Traditional object orientation implements polymorphism inheritance. The *Is-A*\n   relationship indi"
  },
  {
    "path": "doc/record.md",
    "chars": 11298,
    "preview": "###    Declaration\n\n   A `Record` class is declared in a manner identical to that used with Ruby's `Struct`.\n   The clas"
  },
  {
    "path": "functional_ruby.gemspec",
    "chars": 1050,
    "preview": "$LOAD_PATH << File.expand_path('../lib', __FILE__)\n\nrequire 'functional/version'\n\nGem::Specification.new do |s|\n  s.name"
  },
  {
    "path": "lib/functional/abstract_struct.rb",
    "chars": 4753,
    "preview": "require 'functional/protocol'\nrequire 'functional/synchronization'\n\nFunctional::SpecifyProtocol(:Struct) do\n  instance_m"
  },
  {
    "path": "lib/functional/delay.rb",
    "chars": 4075,
    "preview": "require 'functional/synchronization'\n\nmodule Functional\n\n  # Lazy evaluation of a block yielding an immutable result. Us"
  },
  {
    "path": "lib/functional/either.rb",
    "chars": 8721,
    "preview": "require 'functional/abstract_struct'\nrequire 'functional/protocol'\nrequire 'functional/synchronization'\n\nFunctional::Spe"
  },
  {
    "path": "lib/functional/final_struct.rb",
    "chars": 8000,
    "preview": "require 'functional/final_var'\nrequire 'functional/synchronization'\n\nmodule Functional\n\n  # A variation on Ruby's `OpenS"
  },
  {
    "path": "lib/functional/final_var.rb",
    "chars": 5066,
    "preview": "require 'functional/synchronization'\n\nmodule Functional\n\n  # An exception raised when an attempt is made to modify an\n  "
  },
  {
    "path": "lib/functional/memo.rb",
    "chars": 3692,
    "preview": "require 'functional/synchronization'\n\nmodule Functional\n\n  # Memoization is a technique for optimizing functions that ar"
  },
  {
    "path": "lib/functional/method_signature.rb",
    "chars": 2467,
    "preview": "module Functional\n\n  module PatternMatching\n\n    # @!visibility private\n    #\n    # Helper functions used when pattern m"
  },
  {
    "path": "lib/functional/option.rb",
    "chars": 6850,
    "preview": "require 'functional/abstract_struct'\nrequire 'functional/either'\nrequire 'functional/protocol'\nrequire 'functional/synch"
  },
  {
    "path": "lib/functional/pattern_matching.rb",
    "chars": 6045,
    "preview": "require 'functional/method_signature'\n\nmodule Functional\n\n  # As much as I love Ruby I've always been a little disappoin"
  },
  {
    "path": "lib/functional/protocol.rb",
    "chars": 6128,
    "preview": "require 'functional/protocol_info'\n\nmodule Functional\n\n  # An exception indicating a problem during protocol processing."
  },
  {
    "path": "lib/functional/protocol_info.rb",
    "chars": 6312,
    "preview": "require 'functional/synchronization'\n\nmodule Functional\n\n  # An immutable object describing a single protocol and capabl"
  },
  {
    "path": "lib/functional/record.rb",
    "chars": 7616,
    "preview": "require 'functional/abstract_struct'\nrequire 'functional/protocol'\nrequire 'functional/type_check'\n\nmodule Functional\n\n "
  },
  {
    "path": "lib/functional/synchronization.rb",
    "chars": 2062,
    "preview": "module Functional\n\n  # @!visibility private\n  #\n  # Based on work originally done by Petr Chalupa (@pitr-ch) in Concurre"
  },
  {
    "path": "lib/functional/tuple.rb",
    "chars": 8772,
    "preview": "require 'functional/synchronization'\n\nmodule Functional\n\n  # A tuple is a pure functional data strcture that is similar "
  },
  {
    "path": "lib/functional/type_check.rb",
    "chars": 3888,
    "preview": "module Functional\n\n  # Supplies type-checking helpers whenever included.\n  #\n  # @see http://ruby-concurrency.github.io/"
  },
  {
    "path": "lib/functional/union.rb",
    "chars": 5781,
    "preview": "require 'functional/abstract_struct'\nrequire 'functional/synchronization'\n\nmodule Functional\n\n  # An immutable data stru"
  },
  {
    "path": "lib/functional/value_struct.rb",
    "chars": 4969,
    "preview": "require 'functional/synchronization'\n\nmodule Functional\n\n  # A variation on Ruby's `OpenStruct` in which all fields are "
  },
  {
    "path": "lib/functional/version.rb",
    "chars": 72,
    "preview": "module Functional\n\n  # The current gem version.\n  VERSION = '1.3.0'\nend\n"
  },
  {
    "path": "lib/functional.rb",
    "chars": 846,
    "preview": "require 'functional/delay'\nrequire 'functional/either'\nrequire 'functional/final_struct'\nrequire 'functional/final_var'\n"
  },
  {
    "path": "spec/.gitignore",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "spec/functional/abstract_struct_shared.rb",
    "chars": 4335,
    "preview": "shared_examples :abstract_struct do\n\n  specify { Functional::Protocol::Satisfy! struct_class, :Struct }\n\n  let(:other_st"
  },
  {
    "path": "spec/functional/complex_pattern_matching_spec.rb",
    "chars": 5883,
    "preview": "require 'ostruct'\n\nclass Bar\n  def greet\n    return 'Hello, World!'\n  end\nend\n\nclass Foo < Bar\n  include Functional::Pat"
  },
  {
    "path": "spec/functional/delay_spec.rb",
    "chars": 4045,
    "preview": "module Functional\n\n  describe Delay do\n\n    let!(:fulfilled_value) { 10 }\n    let!(:rejected_reason) { StandardError.new"
  },
  {
    "path": "spec/functional/either_spec.rb",
    "chars": 6914,
    "preview": "require_relative 'abstract_struct_shared'\n\nmodule Functional\n\n  describe Either do\n\n    let!(:value){ 42 }\n    let!(:rea"
  },
  {
    "path": "spec/functional/final_struct_spec.rb",
    "chars": 8426,
    "preview": "require 'ostruct'\n\nmodule Functional\n\n  describe FinalStruct do\n\n    context 'instanciation' do\n\n      specify 'with no "
  },
  {
    "path": "spec/functional/final_var_spec.rb",
    "chars": 4382,
    "preview": "module Functional\n\n  describe FinalVar do\n\n    context 'instanciation' do\n\n      it 'is unset when no arguments given' d"
  },
  {
    "path": "spec/functional/memo_spec.rb",
    "chars": 5159,
    "preview": "module Functional\n\n  describe Memo do\n\n    def create_new_memo_class\n      Class.new do\n        include Functional::Memo"
  },
  {
    "path": "spec/functional/option_spec.rb",
    "chars": 8205,
    "preview": "require_relative 'abstract_struct_shared'\nrequire 'securerandom'\n\nmodule Functional\n\n  describe Option do\n\n    let!(:val"
  },
  {
    "path": "spec/functional/pattern_matching_spec.rb",
    "chars": 12559,
    "preview": "require 'ostruct'\n\nmodule Functional\n\n  describe PatternMatching do\n\n    def new_clazz(&block)\n      clazz = Class.new\n "
  },
  {
    "path": "spec/functional/protocol_info_spec.rb",
    "chars": 11710,
    "preview": "module Functional\n\n  describe ProtocolInfo do\n\n    let!(:kitchen_sink) do\n      ProtocolInfo.new(:Everything) do\n       "
  },
  {
    "path": "spec/functional/protocol_spec.rb",
    "chars": 7422,
    "preview": "describe 'protocol specification' do\n\n  before(:each) do\n    @protocol_info = Functional::Protocol.class_variable_get(:@"
  },
  {
    "path": "spec/functional/record_spec.rb",
    "chars": 8419,
    "preview": "require_relative 'abstract_struct_shared'\nrequire 'securerandom'\n\nmodule Functional\n\n  describe Record do\n\n    let!(:exp"
  },
  {
    "path": "spec/functional/tuple_spec.rb",
    "chars": 20759,
    "preview": "require 'rspec/expectations'\n\nRSpec::Matchers.define :be_a_different_tuple_than do |expected|\n  match do |actual|\n    ac"
  },
  {
    "path": "spec/functional/type_check_spec.rb",
    "chars": 3043,
    "preview": "module Functional\n\n  describe TypeCheck do\n\n    context 'Type?' do\n\n      it 'returns true when value is of any of the t"
  },
  {
    "path": "spec/functional/union_spec.rb",
    "chars": 2968,
    "preview": "require_relative 'abstract_struct_shared'\n\nmodule Functional\n\n  describe Union do\n\n    let!(:expected_fields){ [:a, :b, "
  },
  {
    "path": "spec/functional/value_struct_spec.rb",
    "chars": 6166,
    "preview": "require 'ostruct'\n\nmodule Functional\n\n  describe ValueStruct do\n\n    context 'instanciation' do\n\n      specify 'raises a"
  },
  {
    "path": "spec/spec_helper.rb",
    "chars": 675,
    "preview": "require 'simplecov'\nrequire 'coveralls'\n\nSimpleCov.formatter = SimpleCov::Formatter::MultiFormatter[\n  SimpleCov::Format"
  },
  {
    "path": "spec/support/.gitignore",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "tasks/.gitignore",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "tasks/metrics.rake",
    "chars": 183,
    "preview": "desc 'Display LOC (lines of code) report'\ntask :loc do\n  sh 'countloc -r lib'\nend\n\ndesc 'Display code quality analysis r"
  },
  {
    "path": "tasks/update_doc.rake",
    "chars": 1176,
    "preview": "require 'yard'\nYARD::Rake::YardocTask.new\n\nroot = File.expand_path File.join(File.dirname(__FILE__), '..')\n\nnamespace :y"
  }
]

About this extraction

This page contains the full source code of the jdantonio/functional-ruby GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 59 files (269.2 KB), approximately 71.8k tokens, and a symbol index with 339 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!