functional-ruby 0.5.0 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +154 -562
- data/lib/functional/agent.rb +130 -0
- data/lib/functional/all.rb +9 -1
- data/lib/functional/behavior.rb +72 -39
- data/lib/functional/cached_thread_pool.rb +122 -0
- data/lib/functional/concurrency.rb +32 -24
- data/lib/functional/core.rb +2 -62
- data/lib/functional/event.rb +53 -0
- data/lib/functional/event_machine_defer_proxy.rb +23 -0
- data/lib/functional/fixed_thread_pool.rb +89 -0
- data/lib/functional/future.rb +42 -0
- data/lib/functional/global_thread_pool.rb +3 -0
- data/lib/functional/obligation.rb +121 -0
- data/lib/functional/promise.rb +194 -0
- data/lib/functional/thread_pool.rb +61 -0
- data/lib/functional/utilities.rb +114 -0
- data/lib/functional/version.rb +1 -1
- data/lib/functional.rb +1 -0
- data/lib/functional_ruby.rb +1 -0
- data/md/behavior.md +147 -0
- data/md/concurrency.md +465 -0
- data/md/future.md +32 -0
- data/md/obligation.md +32 -0
- data/md/pattern_matching.md +512 -0
- data/md/promise.md +220 -0
- data/md/utilities.md +53 -0
- data/spec/functional/agent_spec.rb +405 -0
- data/spec/functional/behavior_spec.rb +12 -33
- data/spec/functional/cached_thread_pool_spec.rb +112 -0
- data/spec/functional/concurrency_spec.rb +55 -0
- data/spec/functional/event_machine_defer_proxy_spec.rb +246 -0
- data/spec/functional/event_spec.rb +114 -0
- data/spec/functional/fixed_thread_pool_spec.rb +84 -0
- data/spec/functional/future_spec.rb +115 -0
- data/spec/functional/obligation_shared.rb +121 -0
- data/spec/functional/pattern_matching_spec.rb +10 -8
- data/spec/functional/promise_spec.rb +310 -0
- data/spec/functional/thread_pool_shared.rb +209 -0
- data/spec/functional/utilities_spec.rb +149 -0
- data/spec/spec_helper.rb +2 -0
- metadata +55 -5
    
        data/README.md
    CHANGED
    
    | @@ -1,79 +1,77 @@ | |
| 1 | 
            -
            # Functional Ruby []( | 
| 1 | 
            +
            # Functional Ruby [](https://travis-ci.org/jdantonio/functional-ruby?branch=master) [](https://gemnasium.com/jdantonio/functional-ruby)
         | 
| 2 2 |  | 
| 3 | 
            -
            A gem for adding Erlang and  | 
| 3 | 
            +
            A gem for adding Erlang, Clojure, and Go inspired concurrency and functional programming tools to Ruby.
         | 
| 4 4 |  | 
| 5 5 | 
             
            The project is hosted on the following sites:
         | 
| 6 6 |  | 
| 7 7 | 
             
            * [RubyGems project page](https://rubygems.org/gems/functional-ruby)
         | 
| 8 8 | 
             
            * [Source code on GitHub](https://github.com/jdantonio/functional-ruby)
         | 
| 9 | 
            +
            * [YARD documentation on RubyDoc.info](http://rubydoc.info/github/jdantonio/functional-ruby/master/frames)
         | 
| 9 10 | 
             
            * [Continuous integration on Travis-CI](https://travis-ci.org/jdantonio/functional-ruby)
         | 
| 10 11 | 
             
            * [Dependency tracking on Gemnasium](https://gemnasium.com/jdantonio/functional-ruby)
         | 
| 11 12 | 
             
            * [Follow me on Twitter](https://twitter.com/jerrydantonio)
         | 
| 12 13 |  | 
| 13 14 | 
             
            ## Introduction
         | 
| 14 15 |  | 
| 15 | 
            -
            [Ruby](http://www.ruby-lang.org/en/) | 
| 16 | 
            -
             | 
| 17 | 
            -
             | 
| 18 | 
            -
             | 
| 19 | 
            -
             | 
| 20 | 
            -
             | 
| 21 | 
            -
             | 
| 22 | 
            -
             | 
| 23 | 
            -
             | 
| 24 | 
            -
             | 
| 25 | 
            -
             | 
| 26 | 
            -
             | 
| 27 | 
            -
             | 
| 28 | 
            -
             | 
| 29 | 
            -
             | 
| 30 | 
            -
            for helping programmers write Ruby code in a functional style. So I changed the name of the gem
         | 
| 31 | 
            -
            and kept on trucking.
         | 
| 16 | 
            +
            Three things I love are [Ruby](http://www.ruby-lang.org/en/),
         | 
| 17 | 
            +
            [functional](https://en.wikipedia.org/wiki/Functional_programming)
         | 
| 18 | 
            +
            [programming](http://c2.com/cgi/wiki?FunctionalProgramming) and
         | 
| 19 | 
            +
            [concurrency](http://www.amazon.com/s/ref=nb_sb_noss_1?url=search-alias%3Dstripbooks&field-keywords=concurrent%20programming).
         | 
| 20 | 
            +
            Sadly, the first is generally not associated with the other two. First, I reject the
         | 
| 21 | 
            +
            assertion that Ruby is an object-oriented language. It's certainly object-based, since
         | 
| 22 | 
            +
            everything is an object, but entire large-scale programs can be built without ever
         | 
| 23 | 
            +
            defining a single class. Ruby is a true multi-paradigm language and easily supports
         | 
| 24 | 
            +
            many advanced functional techniques. As to concurrency, Ruby's bad reputation is
         | 
| 25 | 
            +
            well earned, but recent versions of Ruby have made significan improvements in that
         | 
| 26 | 
            +
            area. Ruby 2.0 is now a [relevant](https://blog.heroku.com/archives/2013/6/17/ruby-2-default-new-aps)
         | 
| 27 | 
            +
            platform for concurrent applications.
         | 
| 28 | 
            +
             | 
| 29 | 
            +
            This gem is my small and humble attempt to help Ruby reach its full potential as
         | 
| 30 | 
            +
            a highly performant, functional, concurrent programming language.
         | 
| 32 31 |  | 
| 33 32 | 
             
            ### Goals
         | 
| 34 33 |  | 
| 35 | 
            -
             | 
| 34 | 
            +
            My history with high-performance, highly-concurrent programming goes back to my days with C/C++.
         | 
| 35 | 
            +
            I have the same scars as everyone else doing that kind of work with those languages.
         | 
| 36 | 
            +
            I'm fascinated by modern concurrency patterns like [Actors](http://en.wikipedia.org/wiki/Actor_model),
         | 
| 37 | 
            +
            [Agents](http://doc.akka.io/docs/akka/snapshot/java/agents.html), and
         | 
| 38 | 
            +
            [Promises](http://promises-aplus.github.io/promises-spec/). I'm equally fascinated by languages
         | 
| 39 | 
            +
            with strong concurrency support like [Erlang](http://www.erlang.org/doc/getting_started/conc_prog.html),
         | 
| 40 | 
            +
            [Go](http://golang.org/doc/articles/concurrency_patterns.html), and
         | 
| 41 | 
            +
            [Clojure](http://clojure.org/concurrent_programming) (I program with Erlang at work).
         | 
| 42 | 
            +
            My goal is to implement those patterns in Ruby. Specifically:
         | 
| 43 | 
            +
             | 
| 44 | 
            +
            * Stay true to the spirit of the languages providing inspiration
         | 
| 45 | 
            +
            * But implement in a way that makes sense for Ruby
         | 
| 36 46 | 
             
            * Keep the semantics as idiomatic Ruby as possible
         | 
| 37 47 | 
             
            * Support features that make sense in Ruby
         | 
| 38 | 
            -
            * Exclude features that  | 
| 39 | 
            -
            * Avoid using *method_missing*
         | 
| 48 | 
            +
            * Exclude features that don't make sense in Ruby
         | 
| 40 49 | 
             
            * Keep everything small
         | 
| 41 50 | 
             
            * Be as fast as reasonably possible
         | 
| 42 51 |  | 
| 43 | 
            -
             | 
| 44 | 
            -
             | 
| 45 | 
            -
             | 
| 46 | 
            -
             | 
| 47 | 
            -
            *  | 
| 48 | 
            -
            *  | 
| 49 | 
            -
            *  | 
| 50 | 
            -
            *  | 
| 51 | 
            -
            *  | 
| 52 | 
            -
             | 
| 53 | 
            -
             | 
| 54 | 
            -
             | 
| 55 | 
            -
             | 
| 56 | 
            -
             | 
| 57 | 
            -
             | 
| 58 | 
            -
             | 
| 59 | 
            -
             | 
| 60 | 
            -
             | 
| 61 | 
            -
             | 
| 62 | 
            -
             | 
| 63 | 
            -
             | 
| 64 | 
            -
             | 
| 65 | 
            -
             | 
| 66 | 
            -
            I would never advocate turning Ruby into the cesspool complex object creation that Java has
         | 
| 67 | 
            -
            unfortunately become, but occasionally it would be nice to make sure a class implements a set of
         | 
| 68 | 
            -
            required methods. Enter Erlang's [-behavior](http://metajack.im/2008/10/29/custom-behaviors-in-erlang/)
         | 
| 69 | 
            -
            keyword. Basically, you define a `behavior_info` then drop a `behavior` call within a class.
         | 
| 70 | 
            -
            Forget to implement a required method and Ruby will let you know. See the examples below for details.
         | 
| 71 | 
            -
             | 
| 72 | 
            -
            ## Supported Ruby versions
         | 
| 73 | 
            -
             | 
| 74 | 
            -
            MRI 1.9.x and above. Anything else and your mileage may vary.
         | 
| 75 | 
            -
             | 
| 76 | 
            -
            ## Install
         | 
| 52 | 
            +
            ## Features (and Documentation)
         | 
| 53 | 
            +
             | 
| 54 | 
            +
            Several features from Erlang, Co, Clojure, and JavaScript have been implemented this far:
         | 
| 55 | 
            +
             | 
| 56 | 
            +
            * Function overloading with Erlang-style [Pattern Matching](https://github.com/jdantonio/functional-ruby/blob/master/md/pattern_matching.md)
         | 
| 57 | 
            +
            * Interface specifications with Erlang-style [Behavior](https://github.com/jdantonio/functional-ruby/blob/master/md/behavior.md)
         | 
| 58 | 
            +
            * Chained asynchronous operations inspried by JavaScript [Promises](https://github.com/jdantonio/functional-ruby/blob/master/md/promise.md)
         | 
| 59 | 
            +
            * Additional Clojure, Go, and Erlang inspired [Concurrency](https://github.com/jdantonio/functional-ruby/blob/master/md/concurrency.md)
         | 
| 60 | 
            +
            * Several useful functional [Utilities](https://github.com/jdantonio/functional-ruby/blob/master/md/utilities.md)
         | 
| 61 | 
            +
             | 
| 62 | 
            +
            ### Is it any good?
         | 
| 63 | 
            +
             | 
| 64 | 
            +
            [Yes](http://news.ycombinator.com/item?id=3067434)
         | 
| 65 | 
            +
             | 
| 66 | 
            +
            ### Supported Ruby versions
         | 
| 67 | 
            +
             | 
| 68 | 
            +
            MRI 1.9.2, 1.9.3, and 2.0. This library is pure Ruby and has no gem dependencies. It should be
         | 
| 69 | 
            +
            fully compatible with any Ruby interpreter that is 1.9.x compliant. I simply don't know enough
         | 
| 70 | 
            +
            about JRuby, Rubinius, or the others to fully support them. I can promise good karma and
         | 
| 71 | 
            +
            attribution on this page to anyone wishing to take responsibility for verifying compaitibility
         | 
| 72 | 
            +
            with any Ruby other than MRI.
         | 
| 73 | 
            +
             | 
| 74 | 
            +
            ### Install
         | 
| 77 75 |  | 
| 78 76 | 
             
            ```shell
         | 
| 79 77 | 
             
            gem install functional-ruby
         | 
| @@ -93,8 +91,10 @@ that not all users may want, several `require` options are available: | |
| 93 91 | 
             
            ```ruby
         | 
| 94 92 | 
             
            require 'functional/behavior'
         | 
| 95 93 | 
             
            require 'functional/behaviour' # alternate spelling
         | 
| 94 | 
            +
            require 'functional/concurrency'
         | 
| 96 95 | 
             
            require 'functional/pattern_matching'
         | 
| 97 | 
            -
            require 'functional/ | 
| 96 | 
            +
            require 'functional/promise'
         | 
| 97 | 
            +
            require 'functional/utilities'
         | 
| 98 98 | 
             
            ```
         | 
| 99 99 |  | 
| 100 100 | 
             
            If you want everything you can do that, too:
         | 
| @@ -103,18 +103,14 @@ If you want everything you can do that, too: | |
| 103 103 | 
             
            require 'functional/all'
         | 
| 104 104 | 
             
            ```
         | 
| 105 105 |  | 
| 106 | 
            -
            ##  | 
| 106 | 
            +
            ## Examples
         | 
| 107 107 |  | 
| 108 | 
            -
             | 
| 109 | 
            -
             | 
| 108 | 
            +
            For complete examples, see the specific documentation linked above. Below are a
         | 
| 109 | 
            +
            few examples to whet your appetite.
         | 
| 110 110 |  | 
| 111 | 
            -
             | 
| 111 | 
            +
            ### Pattern Matching (Erlang)
         | 
| 112 112 |  | 
| 113 | 
            -
             | 
| 114 | 
            -
            require 'functional/pattern_matching'
         | 
| 115 | 
            -
            ```
         | 
| 116 | 
            -
             | 
| 117 | 
            -
            Then include `PatternMatching` in your class:
         | 
| 113 | 
            +
            Documentation: [Pattern Matching](https://github.com/jdantonio/functional-ruby/blob/master/md/pattern_matching.md)
         | 
| 118 114 |  | 
| 119 115 | 
             
            ```ruby
         | 
| 120 116 | 
             
            require 'functional/pattern_matching'
         | 
| @@ -122,548 +118,144 @@ require 'functional/pattern_matching' | |
| 122 118 | 
             
            class Foo
         | 
| 123 119 | 
             
              include PatternMatching
         | 
| 124 120 |  | 
| 125 | 
            -
               | 
| 126 | 
            -
             | 
| 127 | 
            -
             | 
| 128 | 
            -
            ```
         | 
| 129 | 
            -
             | 
| 130 | 
            -
            You can then define functions with `defn` instead of the normal *def* statement.
         | 
| 131 | 
            -
            The syntax for `defn` is:
         | 
| 132 | 
            -
             | 
| 133 | 
            -
            ```ruby
         | 
| 134 | 
            -
            defn(:symbol_name_of_function, zero, or, more, parameters) { |block, arguments|
         | 
| 135 | 
            -
              # code to execute
         | 
| 136 | 
            -
            }
         | 
| 137 | 
            -
            ```
         | 
| 138 | 
            -
            You can then call your new function just like any other:
         | 
| 139 | 
            -
             | 
| 140 | 
            -
            ```ruby
         | 
| 141 | 
            -
            require 'functional/pattern_matching'
         | 
| 142 | 
            -
             | 
| 143 | 
            -
            class Foo
         | 
| 144 | 
            -
              include PatternMatching
         | 
| 121 | 
            +
              defn(:greet, :male) {
         | 
| 122 | 
            +
                puts "Hello, sir!"
         | 
| 123 | 
            +
              }
         | 
| 145 124 |  | 
| 146 | 
            -
              defn(: | 
| 147 | 
            -
                puts "Hello,  | 
| 125 | 
            +
              defn(:greet, :female) {
         | 
| 126 | 
            +
                puts "Hello, ma'am!"
         | 
| 148 127 | 
             
              }
         | 
| 149 128 | 
             
            end
         | 
| 150 129 |  | 
| 151 130 | 
             
            foo = Foo.new
         | 
| 152 | 
            -
            foo. | 
| 153 | 
            -
             | 
| 154 | 
            -
             | 
| 155 | 
            -
            Patterns to match against are included in the parameter list:
         | 
| 156 | 
            -
             | 
| 157 | 
            -
            ```ruby
         | 
| 158 | 
            -
            defn(:greet, :male) {
         | 
| 159 | 
            -
              puts "Hello, sir!"
         | 
| 160 | 
            -
            }
         | 
| 161 | 
            -
             | 
| 162 | 
            -
            defn(:greet, :female) {
         | 
| 163 | 
            -
              puts "Hello, ma'am!"
         | 
| 164 | 
            -
            }
         | 
| 165 | 
            -
             | 
| 166 | 
            -
            ...
         | 
| 167 | 
            -
             | 
| 168 | 
            -
            foo.hello(:male)   #=> "Hello, sir!"
         | 
| 169 | 
            -
            foo.hello(:female) #=> "Hello, ma'am!"
         | 
| 170 | 
            -
            ```
         | 
| 171 | 
            -
             | 
| 172 | 
            -
            If a particular method call can not be matched a *NoMethodError* is thrown with
         | 
| 173 | 
            -
            a reasonably helpful error message:
         | 
| 174 | 
            -
             | 
| 175 | 
            -
            ```ruby
         | 
| 176 | 
            -
            foo.greet(:unknown) #=> NoMethodError: no method `greet` matching [:unknown] found for class Foo
         | 
| 177 | 
            -
            foo.greet           #=> NoMethodError: no method `greet` matching [] found for class Foo
         | 
| 178 | 
            -
            ```
         | 
| 179 | 
            -
             | 
| 180 | 
            -
            Parameters that are expected to exist but that can take any value are considered
         | 
| 181 | 
            -
            *unbound* parameters. Unbound parameters are specified by the `_` underscore
         | 
| 182 | 
            -
            character or `UNBOUND`:
         | 
| 183 | 
            -
             | 
| 184 | 
            -
            ```ruby
         | 
| 185 | 
            -
            defn(:greet, _) do |name|
         | 
| 186 | 
            -
              "Hello, #{name}!"
         | 
| 187 | 
            -
            end
         | 
| 188 | 
            -
             | 
| 189 | 
            -
            defn(:greet, UNBOUND, UNBOUND) do |first, last|
         | 
| 190 | 
            -
              "Hello, #{first} #{last}!"
         | 
| 191 | 
            -
            end
         | 
| 192 | 
            -
             | 
| 193 | 
            -
            ...
         | 
| 194 | 
            -
             | 
| 195 | 
            -
            foo.greet('Jerry') #=> "Hello, Jerry!"
         | 
| 131 | 
            +
            foo.greet(:male)   #=> "Hello, sir!"
         | 
| 132 | 
            +
            foo.greet(:female) #=> "Hello, ma'am!"
         | 
| 196 133 | 
             
            ```
         | 
| 197 134 |  | 
| 198 | 
            -
             | 
| 199 | 
            -
             | 
| 200 | 
            -
            ```ruby
         | 
| 201 | 
            -
            defn(:greet, _, _) do |first, last|
         | 
| 202 | 
            -
              "Hello, #{first} #{last}!"
         | 
| 203 | 
            -
            end
         | 
| 204 | 
            -
             | 
| 205 | 
            -
            ...
         | 
| 206 | 
            -
             | 
| 207 | 
            -
            foo.greet('Jerry', "D'Antonio") #=> "Hello, Jerry D'Antonio!"
         | 
| 208 | 
            -
            ```
         | 
| 209 | 
            -
             | 
| 210 | 
            -
            If for some reason you don't care about one or more unbound parameters within
         | 
| 211 | 
            -
            the block you can use the `_` underscore character in the block parameters list
         | 
| 212 | 
            -
            as well:
         | 
| 213 | 
            -
             | 
| 214 | 
            -
            ```ruby
         | 
| 215 | 
            -
            defn(:greet, _, _, _) do |first, _, last|
         | 
| 216 | 
            -
              "Hello, #{first} #{last}!"
         | 
| 217 | 
            -
            end
         | 
| 218 | 
            -
             | 
| 219 | 
            -
            ...
         | 
| 220 | 
            -
             | 
| 221 | 
            -
            foo.greet('Jerry', "I'm not going to tell you my middle name!", "D'Antonio") #=> "Hello, Jerry D'Antonio!"
         | 
| 222 | 
            -
            ```
         | 
| 135 | 
            +
            ### Behavior (Erlang)
         | 
| 223 136 |  | 
| 224 | 
            -
             | 
| 225 | 
            -
            function dispatch by hash parameters without having to dig through the hash:
         | 
| 137 | 
            +
            Documentation: [Behavior](https://github.com/jdantonio/functional-ruby/blob/master/md/behavior.md)
         | 
| 226 138 |  | 
| 227 139 | 
             
            ```ruby
         | 
| 228 | 
            -
             | 
| 229 | 
            -
              :foo_bar
         | 
| 230 | 
            -
            }
         | 
| 231 | 
            -
            defn(:hashable, {foo: _}) { |f|
         | 
| 232 | 
            -
              f
         | 
| 233 | 
            -
            }
         | 
| 234 | 
            -
             | 
| 235 | 
            -
            ...
         | 
| 236 | 
            -
             | 
| 237 | 
            -
            foo.hashable({foo: :bar})      #=> :foo_bar
         | 
| 238 | 
            -
            foo.hashable({foo: :baz})      #=> :baz
         | 
| 239 | 
            -
            ```
         | 
| 240 | 
            -
             | 
| 241 | 
            -
            The Ruby idiom of the final parameter being a hash is also supported:
         | 
| 242 | 
            -
             | 
| 243 | 
            -
            ```ruby
         | 
| 244 | 
            -
            defn(:options, _) { |opts|
         | 
| 245 | 
            -
              opts
         | 
| 246 | 
            -
            }
         | 
| 247 | 
            -
             | 
| 248 | 
            -
            ...
         | 
| 249 | 
            -
             | 
| 250 | 
            -
            foo.options(bar: :baz, one: 1, many: 2)
         | 
| 251 | 
            -
            ```
         | 
| 252 | 
            -
             | 
| 253 | 
            -
            As is the Ruby idiom of variable-length argument lists. The constant `ALL` as the last parameter
         | 
| 254 | 
            -
            will match one or more arguments and pass them to the block as an array:
         | 
| 255 | 
            -
             | 
| 256 | 
            -
            ```ruby
         | 
| 257 | 
            -
            defn(:baz, Integer, ALL) { |int, args|
         | 
| 258 | 
            -
              [int, args]
         | 
| 259 | 
            -
            }
         | 
| 260 | 
            -
            defn(:baz, ALL) { |args|
         | 
| 261 | 
            -
              args
         | 
| 262 | 
            -
            }
         | 
| 263 | 
            -
            ```
         | 
| 264 | 
            -
             | 
| 265 | 
            -
            Superclass polymorphism is supported as well. If an object cannot match a method
         | 
| 266 | 
            -
            signature it will defer to the parent class:
         | 
| 267 | 
            -
             | 
| 268 | 
            -
            ```ruby
         | 
| 269 | 
            -
            class Bar
         | 
| 270 | 
            -
              def greet
         | 
| 271 | 
            -
                return 'Hello, World!'
         | 
| 272 | 
            -
              end
         | 
| 273 | 
            -
            end
         | 
| 274 | 
            -
             | 
| 275 | 
            -
            class Foo < Bar
         | 
| 276 | 
            -
              include PatternMatching
         | 
| 277 | 
            -
             | 
| 278 | 
            -
              defn(:greet, _) do |name|
         | 
| 279 | 
            -
                "Hello, #{name}!"
         | 
| 280 | 
            -
              end
         | 
| 281 | 
            -
            end
         | 
| 282 | 
            -
             | 
| 283 | 
            -
            ...
         | 
| 284 | 
            -
             | 
| 285 | 
            -
            foo.greet('Jerry') #=> "Hello, Jerry!"
         | 
| 286 | 
            -
            foo.greet          #=> "Hello, World!"
         | 
| 287 | 
            -
            ```
         | 
| 288 | 
            -
             | 
| 289 | 
            -
            Guard clauses in Erlang are defined with `when` clauses between the parameter list and the function body.
         | 
| 290 | 
            -
            In Ruby, guard clauses are defined by chaining a call to `when` onto the the `defn` call and passing
         | 
| 291 | 
            -
            a block. If the guard clause evaluates to true then the function will match. If the guard evaluates
         | 
| 292 | 
            -
            to false the function will not match and pattern matching will continue:
         | 
| 293 | 
            -
             | 
| 294 | 
            -
            Erlang:
         | 
| 295 | 
            -
             | 
| 296 | 
            -
            ```erlang
         | 
| 297 | 
            -
            old_enough(X) when X >= 16 -> true;
         | 
| 298 | 
            -
            old_enough(_) -> false.
         | 
| 299 | 
            -
            ```
         | 
| 300 | 
            -
             | 
| 301 | 
            -
            Ruby:
         | 
| 302 | 
            -
             | 
| 303 | 
            -
            ```ruby
         | 
| 304 | 
            -
            defn(:old_enough, _){ true }.when{|x| x >= 16 }
         | 
| 305 | 
            -
            defn(:old_enough, _){ false }
         | 
| 306 | 
            -
            ```
         | 
| 307 | 
            -
             | 
| 308 | 
            -
            ### Order Matters
         | 
| 309 | 
            -
             | 
| 310 | 
            -
            As with Erlang, the order of pattern matches is significant. Patterns will be matched
         | 
| 311 | 
            -
            *in the order declared* and the first match will be used. If a particular function call
         | 
| 312 | 
            -
            can be matched by more than one pattern, the *first matched pattern* will be used. It
         | 
| 313 | 
            -
            is the programmer's responsibility to ensure patterns are declared in the correct order.
         | 
| 314 | 
            -
             | 
| 315 | 
            -
            ### Blocks and Procs and Lambdas, oh my!
         | 
| 316 | 
            -
             | 
| 317 | 
            -
            When using this gem it is critical to remember that `defn` takes a block and
         | 
| 318 | 
            -
            that blocks in Ruby have special rules. There are [plenty](https://www.google.com/search?q=ruby+block+proc+lambda)
         | 
| 319 | 
            -
            of good tutorials on the web explaining [blocks](http://www.robertsosinski.com/2008/12/21/understanding-ruby-blocks-procs-and-lambdas/)
         | 
| 320 | 
            -
            and [Procs](https://coderwall.com/p/_-_mha) and [lambdas](http://railsguru.org/2010/03/learn-ruby-procs-blocks-lambda/)
         | 
| 321 | 
            -
            in Ruby. Please read them. Please don't submit a bug report if you use a
         | 
| 322 | 
            -
            `return` statement within your `defn` and your code blows up with a
         | 
| 323 | 
            -
            [LocalJumpError](http://ruby-doc.org/core-2.0/LocalJumpError.html). 
         | 
| 324 | 
            -
             | 
| 325 | 
            -
            ### Examples
         | 
| 326 | 
            -
             | 
| 327 | 
            -
            For more examples see the integration tests in *spec/integration_spec.rb*.
         | 
| 328 | 
            -
             | 
| 329 | 
            -
            #### Simple Functions
         | 
| 330 | 
            -
             | 
| 331 | 
            -
            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/).
         | 
| 332 | 
            -
             | 
| 333 | 
            -
            Erlang:
         | 
| 334 | 
            -
             | 
| 335 | 
            -
            ```erlang
         | 
| 336 | 
            -
            greet(male, Name) ->
         | 
| 337 | 
            -
              io:format("Hello, Mr. ~s!", [Name]);
         | 
| 338 | 
            -
            greet(female, Name) ->
         | 
| 339 | 
            -
              io:format("Hello, Mrs. ~s!", [Name]);
         | 
| 340 | 
            -
            greet(_, Name) ->
         | 
| 341 | 
            -
              io:format("Hello, ~s!", [Name]).
         | 
| 342 | 
            -
            ```
         | 
| 343 | 
            -
             | 
| 344 | 
            -
            Ruby:
         | 
| 140 | 
            +
            require 'functional/behavior'
         | 
| 345 141 |  | 
| 346 | 
            -
             | 
| 347 | 
            -
            require 'functional/pattern_matching'
         | 
| 142 | 
            +
            behaviour_info(:gen_foo, foo: 0, bar: 1)
         | 
| 348 143 |  | 
| 349 144 | 
             
            class Foo
         | 
| 350 | 
            -
               | 
| 145 | 
            +
              behavior(:gen_foo)
         | 
| 351 146 |  | 
| 352 | 
            -
               | 
| 353 | 
            -
                 | 
| 147 | 
            +
              def foo
         | 
| 148 | 
            +
                return 'foo/0'
         | 
| 354 149 | 
             
              end
         | 
| 355 150 |  | 
| 356 | 
            -
               | 
| 357 | 
            -
                 | 
| 358 | 
            -
              }
         | 
| 359 | 
            -
              defn(:greet, :female, _) { |name|
         | 
| 360 | 
            -
                "Hello, Ms. #{name}!"
         | 
| 361 | 
            -
              }
         | 
| 362 | 
            -
              defn(:greet, _, _) { |_, name|
         | 
| 363 | 
            -
                "Hello, #{name}!"
         | 
| 364 | 
            -
              }
         | 
| 365 | 
            -
            end
         | 
| 366 | 
            -
            ```
         | 
| 367 | 
            -
             | 
| 368 | 
            -
            #### Simple Functions with Overloading
         | 
| 369 | 
            -
             | 
| 370 | 
            -
            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/).
         | 
| 371 | 
            -
             | 
| 372 | 
            -
            Erlang:
         | 
| 373 | 
            -
             | 
| 374 | 
            -
            ```erlang
         | 
| 375 | 
            -
            greet(Name) ->
         | 
| 376 | 
            -
              io:format("Hello, ~s!", [Name]).
         | 
| 377 | 
            -
             | 
| 378 | 
            -
            greet(male, Name) ->
         | 
| 379 | 
            -
              io:format("Hello, Mr. ~s!", [Name]);
         | 
| 380 | 
            -
            greet(female, Name) ->
         | 
| 381 | 
            -
              io:format("Hello, Mrs. ~s!", [Name]);
         | 
| 382 | 
            -
            greet(_, Name) ->
         | 
| 383 | 
            -
              io:format("Hello, ~s!", [Name]).
         | 
| 384 | 
            -
            ```
         | 
| 385 | 
            -
             | 
| 386 | 
            -
            Ruby:
         | 
| 387 | 
            -
             | 
| 388 | 
            -
            ```ruby
         | 
| 389 | 
            -
            require 'functional/pattern_matching'
         | 
| 390 | 
            -
             | 
| 391 | 
            -
            class Foo
         | 
| 392 | 
            -
              include PatternMatching
         | 
| 393 | 
            -
             | 
| 394 | 
            -
              defn(:greet, _) do |name|
         | 
| 395 | 
            -
                "Hello, #{name}!"
         | 
| 151 | 
            +
              def bar(one, &block)
         | 
| 152 | 
            +
                return 'bar/1'
         | 
| 396 153 | 
             
              end
         | 
| 397 | 
            -
             | 
| 398 | 
            -
              defn(:greet, :male, _) { |name|
         | 
| 399 | 
            -
                "Hello, Mr. #{name}!"
         | 
| 400 | 
            -
              }
         | 
| 401 | 
            -
              defn(:greet, :female, _) { |name|
         | 
| 402 | 
            -
                "Hello, Ms. #{name}!"
         | 
| 403 | 
            -
              }
         | 
| 404 | 
            -
              defn(:greet, nil, _) { |name|
         | 
| 405 | 
            -
                "Goodbye, #{name}!"
         | 
| 406 | 
            -
              }
         | 
| 407 | 
            -
              defn(:greet, _, _) { |_, name|
         | 
| 408 | 
            -
                "Hello, #{name}!"
         | 
| 409 | 
            -
              }
         | 
| 410 | 
            -
            end
         | 
| 411 | 
            -
            ```
         | 
| 412 | 
            -
             | 
| 413 | 
            -
            #### Constructor Overloading
         | 
| 414 | 
            -
             | 
| 415 | 
            -
            ```ruby
         | 
| 416 | 
            -
            require 'functional/pattern_matching'
         | 
| 417 | 
            -
             | 
| 418 | 
            -
            class Foo
         | 
| 419 | 
            -
              include PatternMatching
         | 
| 420 | 
            -
             | 
| 421 | 
            -
              defn(:initialize) { @name = 'baz' }
         | 
| 422 | 
            -
              defn(:initialize, _) {|name| @name = name.to_s }
         | 
| 423 154 | 
             
            end
         | 
| 424 | 
            -
            ```
         | 
| 425 | 
            -
             | 
| 426 | 
            -
            #### Matching by Class/Datatype
         | 
| 427 | 
            -
             | 
| 428 | 
            -
            ```ruby
         | 
| 429 | 
            -
            require 'functional/pattern_matching'
         | 
| 430 | 
            -
             | 
| 431 | 
            -
            class Foo
         | 
| 432 | 
            -
              include PatternMatching
         | 
| 433 | 
            -
             | 
| 434 | 
            -
              defn(:concat, Integer, Integer) { |first, second|
         | 
| 435 | 
            -
                first + second
         | 
| 436 | 
            -
              }
         | 
| 437 | 
            -
              defn(:concat, Integer, String) { |first, second|
         | 
| 438 | 
            -
                "#{first} #{second}"
         | 
| 439 | 
            -
              }
         | 
| 440 | 
            -
              defn(:concat, String, String) { |first, second|
         | 
| 441 | 
            -
                first + second
         | 
| 442 | 
            -
              }
         | 
| 443 | 
            -
              defn(:concat, Integer, _) { |first, second|
         | 
| 444 | 
            -
                first + second.to_i
         | 
| 445 | 
            -
              }
         | 
| 446 | 
            -
            end
         | 
| 447 | 
            -
            ```
         | 
| 448 155 |  | 
| 449 | 
            -
             | 
| 450 | 
            -
             | 
| 451 | 
            -
            ```ruby
         | 
| 452 | 
            -
            require 'functional/pattern_matching'
         | 
| 453 | 
            -
             | 
| 454 | 
            -
            class Foo
         | 
| 455 | 
            -
              include PatternMatching
         | 
| 456 | 
            -
              
         | 
| 457 | 
            -
              defn(:hashable, {foo: :bar}) { |opts|
         | 
| 458 | 
            -
                # matches any hash with key :foo and value :bar
         | 
| 459 | 
            -
                :foo_bar
         | 
| 460 | 
            -
              }
         | 
| 461 | 
            -
              defn(:hashable, {foo: _, bar: _}) { |f, b|
         | 
| 462 | 
            -
                # matches any hash with keys :foo and :bar
         | 
| 463 | 
            -
                # passes the values associated with those keys to the block
         | 
| 464 | 
            -
                [f, b]
         | 
| 465 | 
            -
              }
         | 
| 466 | 
            -
              defn(:hashable, {foo: _}) { |f|
         | 
| 467 | 
            -
                # matches any hash with key :foo
         | 
| 468 | 
            -
                # passes the value associated with that key to the block
         | 
| 469 | 
            -
                # must appear AFTER the prior match or it will override that one
         | 
| 470 | 
            -
                f
         | 
| 471 | 
            -
              }
         | 
| 472 | 
            -
              defn(:hashable, {}) { ||
         | 
| 473 | 
            -
                # matches an empty hash
         | 
| 474 | 
            -
                :empty
         | 
| 475 | 
            -
              }
         | 
| 476 | 
            -
              defn(:hashable, _) { |opts|
         | 
| 477 | 
            -
                # matches any hash (or any other value)
         | 
| 478 | 
            -
                opts
         | 
| 479 | 
            -
              }
         | 
| 480 | 
            -
            end
         | 
| 481 | 
            -
             | 
| 482 | 
            -
            ...
         | 
| 483 | 
            -
             | 
| 484 | 
            -
            foo.hashable({foo: :bar})      #=> :foo_bar
         | 
| 485 | 
            -
            foo.hashable({foo: :baz})      #=> :baz
         | 
| 486 | 
            -
            foo.hashable({foo: 1, bar: 2}) #=> [1, 2] 
         | 
| 487 | 
            -
            foo.hashable({foo: 1, baz: 2}) #=> 1
         | 
| 488 | 
            -
            foo.hashable({bar: :baz})      #=> {bar: :baz}
         | 
| 489 | 
            -
            foo.hashable({})               #=> :empty 
         | 
| 490 | 
            -
            ```
         | 
| 491 | 
            -
             | 
| 492 | 
            -
            #### Variable Length Argument Lists with ALL
         | 
| 156 | 
            +
            foo = Foo.new
         | 
| 493 157 |  | 
| 494 | 
            -
             | 
| 495 | 
            -
             | 
| 496 | 
            -
               | 
| 497 | 
            -
            }
         | 
| 498 | 
            -
            defn(:all, :one, Integer, ALL) { |int, args|
         | 
| 499 | 
            -
              [int, args]
         | 
| 500 | 
            -
            }
         | 
| 501 | 
            -
            defn(:all, 1, _, ALL) { |var, args|
         | 
| 502 | 
            -
              [var, args]
         | 
| 503 | 
            -
            }
         | 
| 504 | 
            -
            defn(:all, ALL) { | args|
         | 
| 505 | 
            -
              args
         | 
| 506 | 
            -
            }
         | 
| 507 | 
            -
             | 
| 508 | 
            -
            ...
         | 
| 509 | 
            -
             | 
| 510 | 
            -
            foo.all(:one, 'a', 'bee', :see) #=> ['a', 'bee', :see]
         | 
| 511 | 
            -
            foo.all(:one, 1, 'bee', :see)   #=> [1, 'bee', :see]
         | 
| 512 | 
            -
            foo.all(1, 'a', 'bee', :see)    #=> ['a', ['bee', :see]]
         | 
| 513 | 
            -
            foo.all('a', 'bee', :see)       #=> ['a', 'bee', :see]
         | 
| 514 | 
            -
            foo.all()                       #=> NoMethodError: no method `all` matching [] found for class Foo
         | 
| 158 | 
            +
            foo.behaves_as? :gen_foo    #=> true
         | 
| 159 | 
            +
            foo.behaves_as?(:bogus)     #=> false
         | 
| 160 | 
            +
            'foo'.behaves_as? :gen_foo  #=> false
         | 
| 515 161 | 
             
            ```
         | 
| 516 162 |  | 
| 517 | 
            -
             | 
| 518 | 
            -
             | 
| 519 | 
            -
            These examples are based on [Syntax in defnctions: Pattern Matching](http://learnyousomeerlang.com/syntax-in-defnctions)
         | 
| 520 | 
            -
            in [Learn You Some Erlang for Great Good!](http://learnyousomeerlang.com/).
         | 
| 521 | 
            -
             | 
| 522 | 
            -
            Erlang:
         | 
| 523 | 
            -
             | 
| 524 | 
            -
            ```erlang
         | 
| 525 | 
            -
            old_enough(X) when X >= 16 -> true;
         | 
| 526 | 
            -
            old_enough(_) -> false.
         | 
| 527 | 
            -
             | 
| 528 | 
            -
            right_age(X) when X >= 16, X =< 104 ->
         | 
| 529 | 
            -
              true;
         | 
| 530 | 
            -
            right_age(_) ->
         | 
| 531 | 
            -
              false.
         | 
| 532 | 
            -
             | 
| 533 | 
            -
            wrong_age(X) when X < 16; X > 104 ->
         | 
| 534 | 
            -
              true;
         | 
| 535 | 
            -
            wrong_age(_) ->
         | 
| 536 | 
            -
              false.
         | 
| 537 | 
            -
            ```
         | 
| 163 | 
            +
            ### Goroutine (Go)
         | 
| 538 164 |  | 
| 539 165 | 
             
            ```ruby
         | 
| 540 | 
            -
             | 
| 541 | 
            -
            defn(:old_enough, _){ false }
         | 
| 542 | 
            -
             | 
| 543 | 
            -
            defn(:right_age, _) {
         | 
| 544 | 
            -
              true
         | 
| 545 | 
            -
            }.when{|x| x >= 16 && x <= 104 }
         | 
| 546 | 
            -
             | 
| 547 | 
            -
            defn(:right_age, _) {
         | 
| 548 | 
            -
              false
         | 
| 549 | 
            -
            }
         | 
| 550 | 
            -
             | 
| 551 | 
            -
            defn(:wrong_age, _) {
         | 
| 552 | 
            -
              false
         | 
| 553 | 
            -
            }.when{|x| x < 16 || x > 104 }
         | 
| 166 | 
            +
            require 'functional/concurrency'
         | 
| 554 167 |  | 
| 555 | 
            -
             | 
| 556 | 
            -
             | 
| 557 | 
            -
             | 
| 168 | 
            +
            @expected = nil
         | 
| 169 | 
            +
            go(1, 2, 3){|a, b, c| @expected = [c, b, a] }
         | 
| 170 | 
            +
            sleep(0.1)
         | 
| 171 | 
            +
            @expected #=> [3, 2, 1]
         | 
| 558 172 | 
             
            ```
         | 
| 559 173 |  | 
| 560 | 
            -
             | 
| 561 | 
            -
             | 
| 562 | 
            -
            The `behavior` functionality is not imported by default. It requires a separate `require` statement:
         | 
| 174 | 
            +
            ### Agent (Clojure)
         | 
| 563 175 |  | 
| 564 176 | 
             
            ```ruby
         | 
| 565 | 
            -
            require ' | 
| 566 | 
            -
             | 
| 567 | 
            -
             | 
| 568 | 
            -
             | 
| 569 | 
            -
            require 'behaviour'
         | 
| 570 | 
            -
            ```
         | 
| 177 | 
            +
            require 'functional/agent'
         | 
| 178 | 
            +
            # or
         | 
| 179 | 
            +
            require 'functional/concurrency'
         | 
| 571 180 |  | 
| 572 | 
            -
             | 
| 573 | 
            -
             | 
| 574 | 
            -
            `behavior_info` (or `behaviour_info`) is a symbol name for the behavior. The remaining parameter
         | 
| 575 | 
            -
            is a hash of function names and their arity:
         | 
| 181 | 
            +
            score = agent(10)
         | 
| 182 | 
            +
            score.value #=> 10
         | 
| 576 183 |  | 
| 577 | 
            -
             | 
| 578 | 
            -
             | 
| 579 | 
            -
             | 
| 580 | 
            -
            # -or (for the Java/C# crowd)
         | 
| 184 | 
            +
            score << proc{|current| current + 100 }
         | 
| 185 | 
            +
            sleep(0.1)
         | 
| 186 | 
            +
            score.value #=> 110
         | 
| 581 187 |  | 
| 582 | 
            -
             | 
| 188 | 
            +
            score << proc{|current| current * 2 }
         | 
| 189 | 
            +
            sleep(0.1)
         | 
| 190 | 
            +
            deref score #=> 220
         | 
| 583 191 |  | 
| 192 | 
            +
            score << proc{|current| current - 50 }
         | 
| 193 | 
            +
            sleep(0.1)
         | 
| 194 | 
            +
            score.value #=> 170
         | 
| 584 195 | 
             
            ```
         | 
| 585 196 |  | 
| 586 | 
            -
             | 
| 587 | 
            -
            [Method#arity](http://ruby-doc.org/core-1.9.3/Method.html#method-i-arity) function.
         | 
| 588 | 
            -
            Though not explicitly documented, block arguments do not count toward a method's arity.
         | 
| 589 | 
            -
            methods defined using this gem's `defn` function will always have an arity of -1,
         | 
| 590 | 
            -
            regardless of how many overloads are defined.
         | 
| 591 | 
            -
             | 
| 592 | 
            -
            To enforce a behavior on a class simply call the `behavior` function within the class,
         | 
| 593 | 
            -
            passing the name of the desired behavior:
         | 
| 197 | 
            +
            ### Future (Clojure)
         | 
| 594 198 |  | 
| 595 199 | 
             
            ```ruby
         | 
| 596 | 
            -
             | 
| 597 | 
            -
             | 
| 598 | 
            -
             | 
| 599 | 
            -
            end
         | 
| 600 | 
            -
             | 
| 601 | 
            -
            # or use the idiomatic Erlang spelling
         | 
| 602 | 
            -
            class Bar
         | 
| 603 | 
            -
              behaviour(:gen_foo)
         | 
| 604 | 
            -
              ...
         | 
| 605 | 
            -
            end
         | 
| 200 | 
            +
            require 'functional/future'
         | 
| 201 | 
            +
            # or
         | 
| 202 | 
            +
            require 'functional/concurrency'
         | 
| 606 203 |  | 
| 607 | 
            -
             | 
| 608 | 
            -
             | 
| 609 | 
            -
             | 
| 610 | 
            -
             | 
| 611 | 
            -
             | 
| 204 | 
            +
            count = future{ sleep(1); 10 }
         | 
| 205 | 
            +
            count.state #=> :pending
         | 
| 206 | 
            +
            # do stuff...
         | 
| 207 | 
            +
            count.value #=> 10 (after blocking)
         | 
| 208 | 
            +
            deref count #=> 10
         | 
| 612 209 | 
             
            ```
         | 
| 613 210 |  | 
| 614 | 
            -
             | 
| 615 | 
            -
            raise an exception when you try to create an object from the class:
         | 
| 211 | 
            +
            ### Promise (JavaScript)
         | 
| 616 212 |  | 
| 617 | 
            -
             | 
| 618 | 
            -
             | 
| 619 | 
            -
            ```
         | 
| 620 | 
            -
             | 
| 621 | 
            -
            As an added bonus, Ruby [Object](http://ruby-doc.org/core-1.9.3/Object.html) will be
         | 
| 622 | 
            -
            monkey-patched with a `behaves_as?` predicate method.
         | 
| 623 | 
            -
             | 
| 624 | 
            -
            A complete example:
         | 
| 213 | 
            +
            * [Promises/A](http://wiki.commonjs.org/wiki/Promises/A)
         | 
| 214 | 
            +
            * [Promises/A+](http://promises-aplus.github.io/promises-spec/)
         | 
| 625 215 |  | 
| 626 216 | 
             
            ```ruby
         | 
| 627 | 
            -
             | 
| 628 | 
            -
             | 
| 629 | 
            -
             | 
| 630 | 
            -
              behavior(:gen_foo)
         | 
| 631 | 
            -
             | 
| 632 | 
            -
              def foo
         | 
| 633 | 
            -
                return 'foo/0'
         | 
| 634 | 
            -
              end
         | 
| 635 | 
            -
             | 
| 636 | 
            -
              def bar(one, &block)
         | 
| 637 | 
            -
                return 'bar/1'
         | 
| 638 | 
            -
              end
         | 
| 639 | 
            -
             | 
| 640 | 
            -
              def baz(one, two)
         | 
| 641 | 
            -
                return 'baz/2'
         | 
| 642 | 
            -
              end
         | 
| 217 | 
            +
            require 'functional/promise'
         | 
| 218 | 
            +
            # or
         | 
| 219 | 
            +
            require 'functional/concurrency'
         | 
| 643 220 |  | 
| 644 | 
            -
             | 
| 645 | 
            -
                 | 
| 646 | 
            -
             | 
| 647 | 
            -
             | 
| 648 | 
            -
             | 
| 649 | 
            -
             | 
| 650 | 
            -
              end
         | 
| 651 | 
            -
            end
         | 
| 652 | 
            -
             | 
| 653 | 
            -
            foo = Foo.new
         | 
| 654 | 
            -
             | 
| 655 | 
            -
            foo.behaves_as? :gen_foo    #=> true
         | 
| 656 | 
            -
            foo.behaves_as?(:bogus)     #=> false
         | 
| 657 | 
            -
            'foo'.behaves_as? :gen_foo  #=> false
         | 
| 221 | 
            +
            p = promise("Jerry", "D'Antonio"){|a, b| "#{a} #{b}" }.
         | 
| 222 | 
            +
                then{|result| "Hello #{result}." }.
         | 
| 223 | 
            +
                rescue(StandardError){|ex| puts "Boom!" }.
         | 
| 224 | 
            +
                then{|result| "#{result} Would you like to play a game?"}
         | 
| 225 | 
            +
            sleep(1)
         | 
| 226 | 
            +
            p.value #=> "Hello Jerry D'Antonio. Would you like to play a game?" 
         | 
| 658 227 | 
             
            ```
         | 
| 659 228 |  | 
| 660 | 
            -
             | 
| 661 | 
            -
             | 
| 662 | 
            -
            Convenience functions are not imported by default. It require a separate `require` statement:
         | 
| 229 | 
            +
            ### Thread Pools
         | 
| 663 230 |  | 
| 664 231 | 
             
            ```ruby
         | 
| 665 | 
            -
            require 'functional/ | 
| 666 | 
            -
             | 
| 232 | 
            +
            require 'functional/fixed_thread_pool'
         | 
| 233 | 
            +
            require 'functional/cached_thread_pool'
         | 
| 234 | 
            +
            # or
         | 
| 235 | 
            +
            require 'functional/concurrency'
         | 
| 236 | 
            +
             | 
| 237 | 
            +
            pool = Functional::FixedThreadPool.new(10)
         | 
| 238 | 
            +
            @expected = 0
         | 
| 239 | 
            +
            pool.post{ sleep(0.5); @expected += 100 }
         | 
| 240 | 
            +
            pool.post{ sleep(0.5); @expected += 100 }
         | 
| 241 | 
            +
            pool.post{ sleep(0.5); @expected += 100 }
         | 
| 242 | 
            +
            @expected #=> nil
         | 
| 243 | 
            +
            sleep(1)
         | 
| 244 | 
            +
            @expected #=> 300
         | 
| 245 | 
            +
             | 
| 246 | 
            +
            pool = Functional::CachedThreadPool.new
         | 
| 247 | 
            +
            @expected = 0
         | 
| 248 | 
            +
            pool << proc{ sleep(0.5); @expected += 10 }
         | 
| 249 | 
            +
            pool << proc{ sleep(0.5); @expected += 10 }
         | 
| 250 | 
            +
            pool << proc{ sleep(0.5); @expected += 10 }
         | 
| 251 | 
            +
            @expected #=> 0
         | 
| 252 | 
            +
            sleep(1)
         | 
| 253 | 
            +
            @expected #=> 30
         | 
| 254 | 
            +
            ```
         | 
| 255 | 
            +
             | 
| 256 | 
            +
            ### Utilities
         | 
| 257 | 
            +
             | 
| 258 | 
            +
            Documentation: [Utilities](https://github.com/jdantonio/functional-ruby/blob/master/md/utilities.md)
         | 
| 667 259 |  | 
| 668 260 | 
             
            ```ruby
         | 
| 669 261 | 
             
            Infinity #=> Infinity
         | 
| @@ -678,9 +270,9 @@ pp_s [1,2,3,4] #=> "[1, 2, 3, 4]\n" props to Rha7 | |
| 678 270 |  | 
| 679 271 | 
             
            delta(-1, 1) #=> 2
         | 
| 680 272 | 
             
            delta({count: -1}, {count: 1}){|item| item[:count]} #=> 2
         | 
| 681 | 
            -
            ```
         | 
| 682 273 |  | 
| 683 | 
            -
             | 
| 274 | 
            +
            # And many more!
         | 
| 275 | 
            +
            ```
         | 
| 684 276 |  | 
| 685 277 | 
             
            ## Copyright
         | 
| 686 278 |  |