optional 0.0.2 → 0.0.3
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/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
|