From a8cd46f3ad32fc8632313c3f675d91f82e9b7cde Mon Sep 17 00:00:00 2001 From: Mikko Koski Date: Thu, 14 Aug 2014 23:18:02 +0300 Subject: [PATCH 1/2] Tests for combine method --- spec/spec.rb | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/spec/spec.rb b/spec/spec.rb index 4c5c86b..e62c02b 100644 --- a/spec/spec.rb +++ b/spec/spec.rb @@ -156,4 +156,24 @@ def test_case_when(case_value, match_value, non_match_value) expect(Some([1, 2, 3]).map { |arr| arr.map { |v| v * v } }.get).to eql([1, 4, 9]) end end + + describe "combine" do + it "combines multiple Some values" do + expect(Maybe("foo").combine(Maybe("bar")).get).to eql(["foo", "bar"]) + expect(Maybe("foo").combine(Maybe("bar"), Maybe("baz")).get).to eql(["foo", "bar", "baz"]) + expect(Maybe.combine(Maybe("foo"), Maybe("bar"), Maybe("baz")).get).to eql(["foo", "bar", "baz"]) + end + + it "combines with block" do + expect(Maybe("foo").combine(Maybe("bar")) { |a, b| "#{a} + #{b}" }.get).to eql("foo + bar") + expect(Maybe.combine(Maybe("foo"), Maybe("bar")) { |a, b| "#{a} + #{b}" }.get).to eql("foo + bar") + end + + it "returns None if any None" do + expect(Maybe("foo").combine(Maybe(nil)).or_else { false }).to eql(false) + expect(Maybe("foo").combine(Maybe(nil)) { |a, b| "#{a} + #{b}" }.or_else { false }).to eql(false) + expect(Maybe.combine(Maybe("foo"), Maybe(nil)).or_else { false }).to eql(false) + expect(Maybe.combine(Maybe("foo"), Maybe(nil)) { |a, b| "#{a} + #{b}" }.or_else { false }).to eql(false) + end + end end \ No newline at end of file From ba4de84108286ee1a71babc33ed7d39739ccd08a Mon Sep 17 00:00:00 2001 From: Mikko Koski Date: Sat, 16 Aug 2014 00:19:05 +0300 Subject: [PATCH 2/2] Implement combine --- README.md | 13 +++++++++++++ lib/possibly.rb | 13 +++++++++++++ spec/spec.rb | 10 ++++------ 3 files changed, 30 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 2e1fcc1..f961232 100644 --- a/README.md +++ b/README.md @@ -116,6 +116,19 @@ when None end ``` +## `combine([maybes])` + +With `combine` you can create a new `Maybe` which includes an array of values from combined `Maybe`s. If any of the combined `Maybe`s is a `None`, a `None` will be returned. + +``` +mparams = Maybe(params) + +duration = Maybe + .combine(mparams[:start_date], mparams[:end_date]) + .map { |(start, end)| Date.parse(end) - Date.parse(start) } + .get_or_else "Unknown" +``` + ## Examples Instead of using if-clauses to define whether a value is a `nil`, you can wrap the value with `Maybe()` and threat it the same way whether or not it is a `nil` diff --git a/lib/possibly.rb b/lib/possibly.rb index a0287a6..000f8d0 100644 --- a/lib/possibly.rb +++ b/lib/possibly.rb @@ -15,6 +15,19 @@ def ==(other) other.class == self.class end alias_method :eql?, :== + + def combine(*maybes) + Maybe.combine(self, *maybes) + end + + def self.combine(*maybes) + if maybes.any?(&:is_none?) + None() + else + values = maybes.map(&:get) + Maybe(values) + end + end end # Represents a non-empty value diff --git a/spec/spec.rb b/spec/spec.rb index e62c02b..c572f54 100644 --- a/spec/spec.rb +++ b/spec/spec.rb @@ -162,11 +162,9 @@ def test_case_when(case_value, match_value, non_match_value) expect(Maybe("foo").combine(Maybe("bar")).get).to eql(["foo", "bar"]) expect(Maybe("foo").combine(Maybe("bar"), Maybe("baz")).get).to eql(["foo", "bar", "baz"]) expect(Maybe.combine(Maybe("foo"), Maybe("bar"), Maybe("baz")).get).to eql(["foo", "bar", "baz"]) - end - - it "combines with block" do - expect(Maybe("foo").combine(Maybe("bar")) { |a, b| "#{a} + #{b}" }.get).to eql("foo + bar") - expect(Maybe.combine(Maybe("foo"), Maybe("bar")) { |a, b| "#{a} + #{b}" }.get).to eql("foo + bar") + expect(Maybe.combine(Maybe("foo"), Maybe("bar"), Maybe("baz")).map do |(foo, bar, baz)| + "#{foo} and #{bar} and finally, #{baz}" + end.get).to eql ("foo and bar and finally, baz") end it "returns None if any None" do @@ -176,4 +174,4 @@ def test_case_when(case_value, match_value, non_match_value) expect(Maybe.combine(Maybe("foo"), Maybe(nil)) { |a, b| "#{a} + #{b}" }.or_else { false }).to eql(false) end end -end \ No newline at end of file +end