README.rdoc in rumonade-0.2.2 vs README.rdoc in rumonade-0.3.0
- old
+ new
@@ -1,10 +1,12 @@
+{<img src="https://secure.travis-ci.org/ms-ati/rumonade.png?branch=master" alt="Build Status" />}[http://travis-ci.org/ms-ati/rumonade]
+
= Rumonade[https://rubygems.org/gems/rumonade]
Project: github[http://github.com/ms-ati/rumonade]
-Documentation: rubydoc.info[http://rubydoc.info/gems/rumonade/0.2.1/file/README.rdoc]
+Documentation: rubydoc.info[http://rubydoc.info/gems/rumonade/frames]
== A Ruby[http://www.ruby-lang.org] Monad[http://en.wikipedia.org/wiki/Monad_(functional_programming)] Library, Inspired by Scala[http://www.scala-lang.org]
Are you working in both the Scala[http://www.scala-lang.org] and Ruby[http://www.ruby-lang.org] worlds,
and finding that you miss some of the practical benefits of Scala's
@@ -26,12 +28,11 @@
idiom will be implemented to turn blocks which might throw exceptions into Option or Either
results. If this proves useful (and a good fit for Ruby), then more narrow functional catchers can be implemented as well.
== Usage
-Using Option, one can transform _possibly_ _nil_ values in a _functional_ fashion, which can increase clarity while
-eliminating opportunities for bugs:
+==== {Rumonade::Option Option}: handle _possibly_ _nil_ values in a _functional_ fashion:
def format_date_in_march(time_or_date_or_nil)
Option(time_or_date_or_nil). # wraps possibly-nil value in an Option monad (Some or None)
map(&:to_date). # transforms a contained Time value into a Date value
select {|d| d.month == 3}. # filters out non-matching Date values (Some becomes None)
@@ -45,9 +46,39 @@
format_date_in_march(Time.parse('2011-03-21 12:34')) # => "20110321"
Note:
* each step of the chained computations above are functionally isolated
* the value can notionally _start_ as nil, or _become_ nil during a computation, without effecting any other chained computations
+
+==== {Rumonade::Either Either}: handle failures ({Rumonade::Left Left}) and successes ({Rumonade::Right Right}) in a _functional_ fashion:
+
+ def find_person(name)
+ case name
+ when /Jack/i, /John/i
+ Right(name.capitalize)
+ else
+ Left("No such person: #{name.capitalize}")
+ end
+ end
+
+ # success looks like this:
+ find_person("Jack")
+ # => Right("Jack")
+
+ # failure looks like this:
+ find_person("Jill")
+ # => Left("No such person: Jill")
+
+ # on the 'happy path', we can functionally combine and transform successes:
+ (find_person("Jack").lift_to_a + find_person("John").lift_to_a).right.map { |*names| names.join(" and ") }
+ # => Right("Jack and John")
+
+ # while the failure cases are easily handled as well:
+ (find_person("Jack").lift_to_a +
+ find_person("John").lift_to_a +
+ find_person("Jill").lift_to_a +
+ find_person("Joan").lift_to_a).right.map { |*names| names.join(" and ") }
+ # => Left("No such person: Jill", "No such person: Joan")
(_more_ _examples_ _coming_ _soon_...)
== Approach