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 4c5c86b..c572f54 100644 --- a/spec/spec.rb +++ b/spec/spec.rb @@ -156,4 +156,22 @@ 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 -end \ No newline at end of file + + 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"]) + 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 + 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