Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement case_of #5

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 48 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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`
Expand Down
8 changes: 8 additions & 0 deletions lib/possibly.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -85,6 +89,10 @@ def method_missing(*)
self
end

def case_of(other, &block)
block.call if other === self
end

private

def __enumerable_value
Expand Down
12 changes: 12 additions & 0 deletions spec/spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down