diff --git a/README.md b/README.md index 96117a6..75089ee 100644 --- a/README.md +++ b/README.md @@ -114,6 +114,54 @@ when None end ``` +### case_of + +Maybe implements the threequals method in a way which allows it to be used in case expressions pretty neatly: You can match both the type (`None` or `Some`) and the value of `Some`. It almost feels like pattern matching in functional language. However, there's one big shortcoming. Ruby doesn't allow binding the value of `Some` to a variable, so you must use the `get` method to do that. The following does not work in Ruby: + +```ruby +case apples +when Some(1) + puts "one apple" +when Some(x) + puts "#{x} apples" +when None + puts "Unknown number of apples" +end +``` + +Instead, you have to use `get`, which is cubersome: + +```ruby +case apples +when Some(1) + puts "one apple" +when Some + x = apples.get + puts "#{x} apples" +when None + puts "Unknown number of apples" +end +``` + +To workaround this limitation, Maybe implements a method `case_of`, which internally uses case expression: + +```ruby +apples.case_of(Some(1)) { |_| puts "1 apple" } +apples.case_of(Some(Integer)) { |x| puts "#{x} apples" } +apples.case_of(None) { |_| puts "Unknown number of apples" } +``` + +```haml +- apples.case_of(Some(1)) do + = "1 apple" + +- apples.case_of(Some(Integer)) do |x| + = puts "#{x} apples" + +- apples.case_of(None) do + = "Unknown number of apples" +``` + ## 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..fe3c3f8 100644 --- a/lib/possibly.rb +++ b/lib/possibly.rb @@ -54,6 +54,10 @@ def method_missing(method_sym, *args, &block) map { |value| value.send(method_sym, *args, &block) } end + def case_of(other, &block) + block.call(@value) if self === other + end + private def __enumerable_value @@ -85,6 +89,10 @@ def method_missing(*) self end + def case_of(other, &block) + block.call if other === self + end + private def __enumerable_value diff --git a/spec/spec.rb b/spec/spec.rb index bc7709e..e71b411 100644 --- a/spec/spec.rb +++ b/spec/spec.rb @@ -123,6 +123,18 @@ def test_case_when(case_value, match_value, non_match_value) end end + describe "case_of" do + + it "case_of None" do + expect(Maybe(nil).case_of(None) { false }).to eql(false) + end + + it "case_of Some" do + expect(Maybe(1).case_of(Some(1)) { |x| true }).to eql(true) + end + + end + describe "to array" do it "#to_ary" do a, _ = Maybe(1)