optional 0.0.2 → 0.0.3
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile.lock +1 -1
- data/README.md +29 -1
- data/lib/optional/none.rb +2 -2
- data/lib/optional/option/enumerable.rb +5 -0
- data/lib/optional/some.rb +2 -2
- data/optional.gemspec +1 -1
- data/spec/lib/optional/none_spec.rb +1 -0
- data/spec/lib/optional/option/enumerable_spec.rb +8 -0
- data/spec/lib/optional/some_spec.rb +1 -0
- metadata +1 -1
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -1,2 +1,30 @@
|
|
1
1
|
# optional
|
2
|
-
### option types to make nils
|
2
|
+
### option types to make nils a thing of the past
|
3
|
+
|
4
|
+
Tony Hoare, inventor of the null reference, calls it his "billion-dollar mistake". You will be no stranger to the ubiquitous `NoMethodError: undefined method 'foo' for nil:NilClass`. But it doesn't have to be this way.
|
5
|
+
|
6
|
+
There are, crucially, two distinct types of values (or rather lack of values) that are usually, in Ruby, represented as `nil`. There are values that should always be present - and here the fact that they are `nil` actually indicates that an error has occurred somewhere else in your program - and those values that *may or may not be set* - where each case is valid. For example, a person may or may not be wearing a hat.
|
7
|
+
|
8
|
+
class Hat
|
9
|
+
def doff
|
10
|
+
…
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
gwen = Person.create(name: "Gwen", hat: Some[:fedora])
|
15
|
+
charlie = Person.create(name: "Charlie", hat: None)
|
16
|
+
|
17
|
+
class Person
|
18
|
+
|
19
|
+
def greet
|
20
|
+
puts "hello!"
|
21
|
+
hat.do { |h| doff h }
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
|
26
|
+
gwen.hat.match do |m|
|
27
|
+
m.some (:flat_cap) { puts "Hey up!" }
|
28
|
+
m.some (:fedora) { |h| puts "*touches brim of #{h} respectfully*" }
|
29
|
+
m.none { puts "Hello!" }
|
30
|
+
end
|
data/lib/optional/none.rb
CHANGED
data/lib/optional/some.rb
CHANGED
@@ -15,7 +15,7 @@ class Some
|
|
15
15
|
block.nil? ? false : super
|
16
16
|
end
|
17
17
|
|
18
|
-
def value_or
|
18
|
+
def value_or(default=nil)
|
19
19
|
value
|
20
20
|
end
|
21
21
|
|
@@ -28,7 +28,7 @@ class Some
|
|
28
28
|
end
|
29
29
|
|
30
30
|
def == other
|
31
|
-
other.
|
31
|
+
other.is_a?(Some) && value == other.value
|
32
32
|
end
|
33
33
|
|
34
34
|
def | other
|
data/optional.gemspec
CHANGED
@@ -4,6 +4,14 @@ describe Option::Enumerable do
|
|
4
4
|
|
5
5
|
let (:cat) { Cat.new("MOGGIE!") }
|
6
6
|
|
7
|
+
describe "#do" do
|
8
|
+
it "allows ops with side effects to be performed using the value as part of a method chain" do
|
9
|
+
names = ""
|
10
|
+
Some[cat].do { |c| names << c.name }.map(&:name).should eq Some["MOGGIE!"]
|
11
|
+
names.should eq "MOGGIE!"
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
7
15
|
describe "#map" do
|
8
16
|
|
9
17
|
it "maps a some to a some" do
|