option 0.3.1 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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