option 0.3.1 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
data/.travis.yml CHANGED
@@ -7,6 +7,5 @@ rvm:
7
7
  - rbx-18mode
8
8
  - rbx-19mode
9
9
  - ruby-head
10
- - jruby-head
11
10
  - 1.8.7
12
11
  - ree
data/README.md CHANGED
@@ -1,7 +1,9 @@
1
1
  # Option
2
2
 
3
- A Ruby port os Scala's Option monad. Tries to be faithful
4
- but also pragmatic in RE: to ducktyping.
3
+ A Ruby port of Scala's Option monad. Tries to be faithful
4
+ but also pragmatic in RE: to duck typing.
5
+
6
+ Blog post: http://robares.com/2012/09/16/ruby-port-of-scala-option/
5
7
 
6
8
  ## Installation
7
9
 
@@ -54,10 +56,16 @@ None.fold(-> { "missing" }) { |v| v.upcase } #=> missing
54
56
 
55
57
  # filter values returning an option
56
58
  foo.filter { |v| v == "baz" } #=> None
59
+
60
+ # mutation
61
+ foo.inside { |v| v.upcase! } #=> Some("BAR")
57
62
  ```
58
63
 
59
64
  ## Build Status
60
- <a href="http://travis-ci.org/rares/option">![http://travis-ci.org/rares/option](https://secure.travis-ci.org/rares/option.png)</a>
65
+ [![Travis CI](https://secure.travis-ci.org/rares/option.png)](http://travis-ci.org/rares/option)
66
+
67
+ ## Code Climate
68
+ [![Code Climate](https://codeclimate.com/badge.png)](https://codeclimate.com/github/rares/option)
61
69
 
62
70
  ## Contributing
63
71
 
data/lib/option.rb CHANGED
@@ -9,6 +9,15 @@ class OptionClass
9
9
  else or_nil == that
10
10
  end
11
11
  end
12
+
13
+ private
14
+
15
+ def assert_option(result)
16
+ case result
17
+ when OptionClass then return result
18
+ else raise TypeError, "Must be an Option"
19
+ end
20
+ end
12
21
  end
13
22
 
14
23
  class SomeClass < OptionClass
@@ -52,11 +61,7 @@ class SomeClass < OptionClass
52
61
  end
53
62
 
54
63
  def flat_map(&blk)
55
- result = blk.call(get)
56
- case result
57
- when OptionClass then return result
58
- else raise TypeError, "Must be an Option"
59
- end
64
+ assert_option(blk.call(get))
60
65
  end
61
66
 
62
67
  def fold(if_empty, &blk)
@@ -75,6 +80,10 @@ class SomeClass < OptionClass
75
80
  blk.call(get)
76
81
  self
77
82
  end
83
+
84
+ def or_else(&blk)
85
+ self
86
+ end
78
87
  end
79
88
 
80
89
  class NoneClass < OptionClass
@@ -130,6 +139,10 @@ class NoneClass < OptionClass
130
139
  def inside(&blk)
131
140
  self
132
141
  end
142
+
143
+ def or_else(&blk)
144
+ assert_option(blk.call)
145
+ end
133
146
  end
134
147
 
135
148
  None = NoneClass.new
@@ -1,3 +1,3 @@
1
1
  module Option
2
- VERSION = "0.3.1"
2
+ VERSION = "0.4.0"
3
3
  end
data/spec/option_spec.rb CHANGED
@@ -1,8 +1,23 @@
1
1
  require "minitest/autorun"
2
+ require "minitest/pride"
2
3
  require "minitest/spec"
3
4
 
4
5
  require "option"
5
6
 
7
+ module MiniTest::Assertions
8
+
9
+ def assert_some(value, option, msg = nil)
10
+ assert (option.is_a?(Some) && option.or_nil == value), "Expected Some(#{value})"
11
+ end
12
+
13
+ def assert_none(value, option, msg = nil)
14
+ assert option == None, "Expected None"
15
+ end
16
+ end
17
+
18
+ OptionClass.infect_an_assertion :assert_some, :must_be_some
19
+ OptionClass.infect_an_assertion :assert_none, :must_be_none
20
+
6
21
  def value
7
22
  12
8
23
  end
@@ -41,11 +56,11 @@ describe NoneClass do
41
56
  end
42
57
 
43
58
  it "#map should return itself" do
44
- None.map {}.must_equal(None)
59
+ None.map {}.must_be_none
45
60
  end
46
61
 
47
62
  it "#flat_map should return itself" do
48
- None.flat_map {}.must_equal(None)
63
+ None.flat_map {}.must_be_none
49
64
  end
50
65
 
51
66
  it "#exists? should return false" do
@@ -57,11 +72,11 @@ describe NoneClass do
57
72
  end
58
73
 
59
74
  it "#filter with a true predicate returns itself" do
60
- Option(value).filter { |i| i == 12 }.must_equal(Option(value))
75
+ Option(value).filter { |i| i == 12 }.must_be_some(value)
61
76
  end
62
77
 
63
78
  it "#filter with a false predicate returns None" do
64
- Option(value).filter { |i| i == 1 }.must_equal(None)
79
+ Option(value).filter { |i| i == 1 }.must_be_none
65
80
  end
66
81
 
67
82
  it "should be aliased to None" do
@@ -73,6 +88,14 @@ describe NoneClass do
73
88
  None.inside { |v| expected = value }
74
89
  expected.must_be_nil
75
90
  end
91
+
92
+ it "#or_else should invoke the block and return an Option" do
93
+ None.or_else { Some(value) }.must_be_some(value)
94
+ end
95
+
96
+ it "#or_else should raise a TypeError if an Option is not returned" do
97
+ lambda { None.or_else { value } }.must_raise TypeError
98
+ end
76
99
  end
77
100
 
78
101
  describe SomeClass do
@@ -116,7 +139,7 @@ describe SomeClass do
116
139
  end
117
140
 
118
141
  it "#map should return the result of the proc over the value in an Option" do
119
- Some(value).map { |v| v * 2 }.must_equal(Some(24))
142
+ Some(value).map { |v| v * 2 }.must_be_some(24)
120
143
  end
121
144
 
122
145
  it "#flat_map should raise TypeError if the returned value is not an Option" do
@@ -124,11 +147,11 @@ describe SomeClass do
124
147
  end
125
148
 
126
149
  it "#flat_map should return an Option value from the block" do
127
- Some(value).flat_map { |v| Option(v * 2) }.must_equal(Some(24))
150
+ Some(value).flat_map { |v| Option(v * 2) }.must_be_some(24)
128
151
  end
129
152
 
130
153
  it "#flat_map can return None from the block" do
131
- Some(value).flat_map { |_| None }.must_equal(None)
154
+ Some(value).flat_map { |_| None }.must_be_none
132
155
  end
133
156
 
134
157
  it "#exists? should return true when the block evaluates true" do
@@ -144,32 +167,36 @@ describe SomeClass do
144
167
  end
145
168
 
146
169
  it "#filter should return itself" do
147
- None.filter { |i| i == 0 }.must_equal(None)
170
+ None.filter { |i| i == 0 }.must_be_none
148
171
  end
149
172
 
150
173
  it "#inside should invoke the proc and return itself" do
151
174
  expected = nil
152
- Some(value).inside { |v| expected = v }.must_equal(Some(value))
175
+ Some(value).inside { |v| expected = v }.must_be_some(value)
153
176
  expected.must_equal(value)
154
177
  end
155
178
 
179
+ it "#or_else should return itself" do
180
+ Some(value).or_else { None }.must_be_some(value)
181
+ end
182
+
156
183
  it "should wrap the creation of a Some" do
157
184
  Some(value).must_be_instance_of(SomeClass)
158
185
  end
159
186
 
160
187
  it "should be aliased to Some" do
161
- Some.new(value).must_equal(Some(value))
188
+ Some.new(value).must_be_some(value)
162
189
  end
163
190
  end
164
191
 
165
192
  describe OptionClass do
166
193
 
167
194
  it "must return a some if the passed value is not nil" do
168
- Option(value).must_equal(Some(value))
195
+ Option(value).must_be_some(value)
169
196
  end
170
197
 
171
198
  it "must return a None if the passed value is nil" do
172
- Option(nil).must_equal(None)
199
+ Option(nil).must_be_none
173
200
  end
174
201
 
175
202
  it "should do equality checks against the boxed value" do
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: option
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.1
4
+ version: 0.4.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-09-20 00:00:00.000000000 Z
12
+ date: 2012-10-07 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rake
16
- requirement: &70142759119300 !ruby/object:Gem::Requirement
16
+ requirement: &70193288139160 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - =
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: 0.9.2.2
22
22
  type: :development
23
23
  prerelease: false
24
- version_requirements: *70142759119300
24
+ version_requirements: *70193288139160
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: minitest
27
- requirement: &70142759118800 !ruby/object:Gem::Requirement
27
+ requirement: &70193288138600 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - =
@@ -32,7 +32,7 @@ dependencies:
32
32
  version: 3.4.0
33
33
  type: :development
34
34
  prerelease: false
35
- version_requirements: *70142759118800
35
+ version_requirements: *70193288138600
36
36
  description: Ruby port of Scala's Option Monad
37
37
  email:
38
38
  - rob.ares@gmail.com