From c6c268b24c5a81d04ac370ce1e3ee6d0957e1b75 Mon Sep 17 00:00:00 2001 From: Mikko Koski Date: Sun, 3 Aug 2014 21:22:28 +0300 Subject: [PATCH 1/2] Add case_of to README --- README.md | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/README.md b/README.md index 96117a6..f4fb362 100644 --- a/README.md +++ b/README.md @@ -114,6 +114,29 @@ when None end ``` +### case_of + +Ruby doesn't support binding the value of Some to a variable. 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 +``` + +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(Int)) { |x| puts "#{x} apples" } +apples.case_of(None) { |_| puts "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` From 4b3da1812d542d8961f227faf03bb113f09a473e Mon Sep 17 00:00:00 2001 From: Mikko Koski Date: Mon, 4 Aug 2014 22:58:41 +0300 Subject: [PATCH 2/2] case_of --- README.md | 29 +++++++++++++++++++++++++++-- lib/possibly.rb | 8 ++++++++ spec/spec.rb | 12 ++++++++++++ 3 files changed, 47 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index f4fb362..75089ee 100644 --- a/README.md +++ b/README.md @@ -116,7 +116,7 @@ end ### case_of -Ruby doesn't support binding the value of Some to a variable. The following does not work in Ruby: +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 @@ -129,14 +129,39 @@ when None 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(Int)) { |x| puts "#{x} apples" } +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)