ruby-maybe 0.2.0 → 0.3.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.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/.travis.yml +2 -2
- data/Gemfile +3 -1
- data/Gemfile.lock +18 -1
- data/README.md +11 -18
- data/Rakefile +1 -1
- data/lib/ruby-maybe.rb +3 -69
- data/lib/ruby-maybe/just.rb +46 -0
- data/lib/ruby-maybe/maybe.rb +9 -0
- data/lib/ruby-maybe/nothing.rb +29 -0
- data/ruby-maybe.gemspec +1 -1
- data/spec/integration_spec.rb +31 -0
- data/spec/just_spec.rb +56 -0
- data/spec/maybe_spec.rb +15 -0
- data/spec/nothing_spec.rb +54 -0
- data/spec/spec_helper.rb +4 -0
- metadata +10 -3
- data/spec/ruby-maybe_spec.rb +0 -102
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c83820565d7167780e0d0d9a58a5f71fc91488ce
|
4
|
+
data.tar.gz: aac84db4cf46cfeae3a3df738962347e2cc65a58
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: cfa21d65a6ffda9aa908ad01593ed4ba705f706292b4b5721e129aec1765874e8013894a1767e472c6c3521eab86539559967d91c18cdd0e8f670015b290e5d7
|
7
|
+
data.tar.gz: ef8ea4a3bac49820d5ac6089193dbb6ed687151fa3a1efb897be1cc31e62fb08cfb9f98b55b0f34032f14db96e7a3f70f7dc11efb0fdad3a3c982b9882ecef2d
|
data/.gitignore
CHANGED
data/.travis.yml
CHANGED
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,10 +1,27 @@
|
|
1
1
|
GEM
|
2
|
-
remote:
|
2
|
+
remote: https://rubygems.org/
|
3
3
|
specs:
|
4
|
+
colorize (0.5.8)
|
5
|
+
coveralls (0.6.7)
|
6
|
+
colorize
|
7
|
+
multi_json (~> 1.3)
|
8
|
+
rest-client
|
9
|
+
simplecov (>= 0.7)
|
10
|
+
thor
|
11
|
+
mime-types (1.23)
|
12
|
+
multi_json (1.7.3)
|
4
13
|
rake (10.0.3)
|
14
|
+
rest-client (1.6.7)
|
15
|
+
mime-types (>= 1.16)
|
16
|
+
simplecov (0.7.1)
|
17
|
+
multi_json (~> 1.0)
|
18
|
+
simplecov-html (~> 0.7.1)
|
19
|
+
simplecov-html (0.7.1)
|
20
|
+
thor (0.18.1)
|
5
21
|
|
6
22
|
PLATFORMS
|
7
23
|
ruby
|
8
24
|
|
9
25
|
DEPENDENCIES
|
26
|
+
coveralls
|
10
27
|
rake
|
data/README.md
CHANGED
@@ -4,7 +4,17 @@
|
|
4
4
|
|
5
5
|

|
6
6
|
|
7
|
-
##
|
7
|
+
## Installation
|
8
|
+
|
9
|
+
Either include in your Gemfile:
|
10
|
+
|
11
|
+
gem 'ruby-maybe'
|
12
|
+
|
13
|
+
Or, install for your system:
|
14
|
+
|
15
|
+
> gem install ruby-maybe
|
16
|
+
|
17
|
+
## Usage
|
8
18
|
|
9
19
|
### The Basics
|
10
20
|
|
@@ -83,20 +93,3 @@ works for Nothing:
|
|
83
93
|
|
84
94
|
Nothing.new + Just.new(5) # => Nothing.new
|
85
95
|
Just.new(0) * Nothing.new / Just.new(1) # => Nothing.new
|
86
|
-
|
87
|
-
### Extracting Values from a Maybe
|
88
|
-
|
89
|
-
Try not to do this. Please. Monads are best used when we play nice and let the Monad look after our values. Of course,
|
90
|
-
you're thinking "well at some point I have to take it out to write it out or stick it in a web response on something
|
91
|
-
right?". Yes, of course. But its best if these cases have abstractions that can receive monads or are structured as
|
92
|
-
Monads themselves (some languages like Haskell include Monads for IO, Web request processing [etc](http://learnyouahaskell.com/a-fistful-of-monads)).
|
93
|
-
|
94
|
-
## Installation
|
95
|
-
|
96
|
-
Either include in your Gemfile:
|
97
|
-
|
98
|
-
gem 'ruby-maybe'
|
99
|
-
|
100
|
-
Or, install for your system:
|
101
|
-
|
102
|
-
> gem install ruby-maybe
|
data/Rakefile
CHANGED
data/lib/ruby-maybe.rb
CHANGED
@@ -1,69 +1,3 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
class Just < Maybe
|
5
|
-
def method_missing(method_name, *args, &block)
|
6
|
-
values = args.map { |arg|
|
7
|
-
return Nothing.new if arg == Nothing.new
|
8
|
-
arg.kind_of?(Just) ? arg.value : arg
|
9
|
-
}
|
10
|
-
|
11
|
-
Just.new(@value.public_send(method_name, *values, &block))
|
12
|
-
end
|
13
|
-
|
14
|
-
def initialize(value)
|
15
|
-
@value = value
|
16
|
-
end
|
17
|
-
|
18
|
-
def bind(&block)
|
19
|
-
computed = block.call(@value)
|
20
|
-
warn("Not returning a Maybe from #bind is really bad form...") unless computed.kind_of?(Maybe)
|
21
|
-
computed
|
22
|
-
end
|
23
|
-
|
24
|
-
def ==(object)
|
25
|
-
if object.class == Just
|
26
|
-
object.value == self.value
|
27
|
-
else
|
28
|
-
false
|
29
|
-
end
|
30
|
-
end
|
31
|
-
|
32
|
-
def _extract!
|
33
|
-
value
|
34
|
-
end
|
35
|
-
|
36
|
-
protected
|
37
|
-
|
38
|
-
def value
|
39
|
-
@value
|
40
|
-
end
|
41
|
-
end
|
42
|
-
|
43
|
-
class Nothing < Maybe
|
44
|
-
def method_missing(method_name, *args, &block)
|
45
|
-
Nothing.new
|
46
|
-
end
|
47
|
-
|
48
|
-
def bind
|
49
|
-
Nothing.new
|
50
|
-
end
|
51
|
-
|
52
|
-
def ==(object)
|
53
|
-
if object.class == Nothing
|
54
|
-
true
|
55
|
-
else
|
56
|
-
false
|
57
|
-
end
|
58
|
-
end
|
59
|
-
|
60
|
-
def _extract!
|
61
|
-
raise AttemptedExtract.new
|
62
|
-
end
|
63
|
-
|
64
|
-
class AttemptedExtract < Exception
|
65
|
-
def initialize
|
66
|
-
super("Attempted to extract value from Nothing")
|
67
|
-
end
|
68
|
-
end
|
69
|
-
end
|
1
|
+
require 'ruby-maybe/maybe'
|
2
|
+
require 'ruby-maybe/just'
|
3
|
+
require 'ruby-maybe/nothing'
|
@@ -0,0 +1,46 @@
|
|
1
|
+
class Just < Maybe
|
2
|
+
def method_missing(method_name, *args, &block)
|
3
|
+
values = args.map { |arg|
|
4
|
+
return Nothing.new if arg == Nothing.new
|
5
|
+
arg.kind_of?(Just) ? arg.value : arg
|
6
|
+
}
|
7
|
+
|
8
|
+
Just.new(@value.public_send(method_name, *values, &block))
|
9
|
+
end
|
10
|
+
|
11
|
+
def initialize(value)
|
12
|
+
@value = value
|
13
|
+
end
|
14
|
+
|
15
|
+
def bind(&block)
|
16
|
+
computed = block.call(@value)
|
17
|
+
warn("Not returning a Maybe from #bind is really bad form...") unless computed.kind_of?(Maybe)
|
18
|
+
computed
|
19
|
+
end
|
20
|
+
|
21
|
+
def map(&block)
|
22
|
+
Just.new(block.call(@value))
|
23
|
+
end
|
24
|
+
|
25
|
+
def or(&block)
|
26
|
+
self
|
27
|
+
end
|
28
|
+
|
29
|
+
def get(&block)
|
30
|
+
@value
|
31
|
+
end
|
32
|
+
|
33
|
+
def ==(object)
|
34
|
+
if object.class == Just
|
35
|
+
object.value == self.value
|
36
|
+
else
|
37
|
+
false
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
protected
|
42
|
+
|
43
|
+
def value
|
44
|
+
@value
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
class Nothing < Maybe
|
2
|
+
def method_missing(method_name, *args, &block)
|
3
|
+
Nothing.new
|
4
|
+
end
|
5
|
+
|
6
|
+
def bind
|
7
|
+
Nothing.new
|
8
|
+
end
|
9
|
+
|
10
|
+
def map
|
11
|
+
Nothing.new
|
12
|
+
end
|
13
|
+
|
14
|
+
def or(&block)
|
15
|
+
block.call
|
16
|
+
end
|
17
|
+
|
18
|
+
def get(&block)
|
19
|
+
block.call
|
20
|
+
end
|
21
|
+
|
22
|
+
def ==(object)
|
23
|
+
if object.class == Nothing
|
24
|
+
true
|
25
|
+
else
|
26
|
+
false
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
data/ruby-maybe.gemspec
CHANGED
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'ruby-maybe'
|
3
|
+
|
4
|
+
describe "Integration Specs" do
|
5
|
+
it "works as expected" do
|
6
|
+
Just.new(5).bind { |val|
|
7
|
+
Just.new(val).map { |val|
|
8
|
+
val * 3
|
9
|
+
}
|
10
|
+
}.bind { |val|
|
11
|
+
if (val > 10)
|
12
|
+
Nothing.new
|
13
|
+
else
|
14
|
+
Just.new(val) + 1
|
15
|
+
end
|
16
|
+
}.must_equal(Nothing.new)
|
17
|
+
end
|
18
|
+
|
19
|
+
it "has the correct interface" do
|
20
|
+
has_method(:bind)
|
21
|
+
has_method(:map)
|
22
|
+
has_method(:or)
|
23
|
+
has_method(:get)
|
24
|
+
has_method(:==)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def has_method(name)
|
29
|
+
assert(Just.method_defined?(name), "Just does not respond to #{name}")
|
30
|
+
assert(Nothing.method_defined?(name), "Nothing does not respond to #{name}")
|
31
|
+
end
|
data/spec/just_spec.rb
ADDED
@@ -0,0 +1,56 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'ruby-maybe'
|
3
|
+
|
4
|
+
describe "Just" do
|
5
|
+
describe "#bind" do
|
6
|
+
it "applys the passed block to its boxed value" do
|
7
|
+
Just.new(5).bind { |val| Just.new(val * 2) }.must_equal Just.new(10)
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
describe "#or" do
|
12
|
+
it "ignores arg and returns self" do
|
13
|
+
(Just.new(5).or { 0 }).must_equal Just.new(5)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
describe "#get" do
|
18
|
+
it "ignores arg and returns value" do
|
19
|
+
(Just.new(5).get { 0 }).must_equal 5
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
describe "#==" do
|
24
|
+
it "returns false if the passed object is not a Just" do
|
25
|
+
(Just.new(5) == 5).must_equal false
|
26
|
+
end
|
27
|
+
|
28
|
+
it "returns true if the passed object is a Just with the same value" do
|
29
|
+
(Just.new(5) == Just.new(5)).must_equal true
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
describe "method lifting" do
|
34
|
+
it "allows using a method for the contained type" do
|
35
|
+
just = Just.new(5)
|
36
|
+
just.+(5).must_equal(Just.new(10))
|
37
|
+
end
|
38
|
+
|
39
|
+
it "allows passed arguments to be Maybe instances" do
|
40
|
+
just = Just.new(5)
|
41
|
+
just.+(Just.new(5)).must_equal(Just.new(10))
|
42
|
+
end
|
43
|
+
|
44
|
+
it "returns Nothing if any argument is Nothing" do
|
45
|
+
just = Just.new("Hello")
|
46
|
+
just.slice(Just.new(0), Nothing.new).must_equal(Nothing.new)
|
47
|
+
end
|
48
|
+
|
49
|
+
it "passes blocks correctly" do
|
50
|
+
count = 0
|
51
|
+
just = Just.new(5)
|
52
|
+
just.times { |i| count += i }
|
53
|
+
count.must_equal(10)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
data/spec/maybe_spec.rb
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'ruby-maybe'
|
3
|
+
|
4
|
+
describe "Maybe" do
|
5
|
+
describe "#from" do
|
6
|
+
it "returns Nothing if passed nil" do
|
7
|
+
Maybe.from(nil).must_equal Nothing.new
|
8
|
+
end
|
9
|
+
|
10
|
+
it "returns Just if passed non-nil value" do
|
11
|
+
Maybe.from(false).must_equal Just.new(false)
|
12
|
+
Maybe.from(11).must_equal Just.new(11)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'ruby-maybe'
|
3
|
+
|
4
|
+
describe "Nothing" do
|
5
|
+
describe "#bind" do
|
6
|
+
it "does not execute the passed block" do
|
7
|
+
executed = false
|
8
|
+
Nothing.new.bind { |val| executed = true }
|
9
|
+
executed.must_equal false
|
10
|
+
end
|
11
|
+
|
12
|
+
it "returns a Nothing" do
|
13
|
+
Nothing.new.bind { |val| val }.kind_of?(Nothing).must_equal true
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
describe "#map" do
|
18
|
+
it "returns Nothing" do
|
19
|
+
Nothing.new.map { |val| val }.must_equal Nothing.new
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
describe "#or" do
|
24
|
+
it "evaluates arg, returning result" do
|
25
|
+
(Nothing.new.or { Just.new(5) }).must_equal Just.new(5)
|
26
|
+
end
|
27
|
+
|
28
|
+
it "chain or calls, returning last value" do
|
29
|
+
(Nothing.new.or { Nothing.new.or { Just.new(10) } }).must_equal Just.new(10)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
describe "#get" do
|
34
|
+
it "evaluates arg, returning result" do
|
35
|
+
(Nothing.new.get { 5 }).must_equal 5
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
describe "#==" do
|
40
|
+
it "returns false if the passed object is not a Nothing" do
|
41
|
+
(Nothing.new == 5).must_equal false
|
42
|
+
end
|
43
|
+
|
44
|
+
it "returns true if the passed object is a Nothing" do
|
45
|
+
(Nothing.new == Nothing.new).must_equal true
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
describe "method lifting" do
|
50
|
+
it "returns Nothing for any method call" do
|
51
|
+
Nothing.new.missing.must_equal(Nothing.new)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
data/spec/spec_helper.rb
ADDED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ruby-maybe
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Callum Stott
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2013-
|
11
|
+
date: 2013-06-25 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description:
|
14
14
|
email:
|
@@ -25,8 +25,15 @@ files:
|
|
25
25
|
- README.md
|
26
26
|
- Rakefile
|
27
27
|
- lib/ruby-maybe.rb
|
28
|
+
- lib/ruby-maybe/just.rb
|
29
|
+
- lib/ruby-maybe/maybe.rb
|
30
|
+
- lib/ruby-maybe/nothing.rb
|
28
31
|
- ruby-maybe.gemspec
|
29
|
-
- spec/
|
32
|
+
- spec/integration_spec.rb
|
33
|
+
- spec/just_spec.rb
|
34
|
+
- spec/maybe_spec.rb
|
35
|
+
- spec/nothing_spec.rb
|
36
|
+
- spec/spec_helper.rb
|
30
37
|
homepage:
|
31
38
|
licenses:
|
32
39
|
- MIT
|
data/spec/ruby-maybe_spec.rb
DELETED
@@ -1,102 +0,0 @@
|
|
1
|
-
require 'minitest/autorun'
|
2
|
-
require 'ruby-maybe'
|
3
|
-
|
4
|
-
describe "Just" do
|
5
|
-
describe "#bind" do
|
6
|
-
it "applys the passed block to its boxed value" do
|
7
|
-
Just.new(5).bind { |val| Just.new(val * 2) }.must_equal Just.new(10)
|
8
|
-
end
|
9
|
-
end
|
10
|
-
|
11
|
-
describe "#==" do
|
12
|
-
it "returns false if the passed object is not a Just" do
|
13
|
-
(Just.new(5) == 5).must_equal false
|
14
|
-
end
|
15
|
-
|
16
|
-
it "returns true if the passed object is a Just with the same value" do
|
17
|
-
(Just.new(5) == Just.new(5)).must_equal true
|
18
|
-
end
|
19
|
-
end
|
20
|
-
|
21
|
-
describe "method lifting" do
|
22
|
-
it "allows using a method for the contained type" do
|
23
|
-
just = Just.new(5)
|
24
|
-
just.+(5).must_equal(Just.new(10))
|
25
|
-
end
|
26
|
-
|
27
|
-
it "allows passed arguments to be Maybe instances" do
|
28
|
-
just = Just.new(5)
|
29
|
-
just.+(Just.new(5)).must_equal(Just.new(10))
|
30
|
-
end
|
31
|
-
|
32
|
-
it "returns Nothing if any argument is Nothing" do
|
33
|
-
just = Just.new("Hello")
|
34
|
-
just.slice(Just.new(0), Nothing.new).must_equal(Nothing.new)
|
35
|
-
end
|
36
|
-
|
37
|
-
it "passes blocks correctly" do
|
38
|
-
count = 0
|
39
|
-
just = Just.new(5)
|
40
|
-
just.times { |i| count += i }
|
41
|
-
count.must_equal(10)
|
42
|
-
end
|
43
|
-
end
|
44
|
-
|
45
|
-
describe "#_extract!" do
|
46
|
-
it "returns the contained value" do
|
47
|
-
Just.new(5)._extract!.must_equal(5)
|
48
|
-
end
|
49
|
-
end
|
50
|
-
end
|
51
|
-
|
52
|
-
describe "Nothing" do
|
53
|
-
describe "#bind" do
|
54
|
-
it "does not execute the passed block" do
|
55
|
-
executed = false
|
56
|
-
Nothing.new.bind { |val| executed = true }
|
57
|
-
executed.must_equal false
|
58
|
-
end
|
59
|
-
|
60
|
-
it "returns a Nothing" do
|
61
|
-
Nothing.new.bind { |val| val }.kind_of?(Nothing).must_equal true
|
62
|
-
end
|
63
|
-
end
|
64
|
-
|
65
|
-
describe "#==" do
|
66
|
-
it "returns false if the passed object is not a Nothing" do
|
67
|
-
(Nothing.new == 5).must_equal false
|
68
|
-
end
|
69
|
-
|
70
|
-
it "returns true if the passed object is a Nothing" do
|
71
|
-
(Nothing.new == Nothing.new).must_equal true
|
72
|
-
end
|
73
|
-
end
|
74
|
-
|
75
|
-
describe "method lifting" do
|
76
|
-
it "returns Nothing for any method call" do
|
77
|
-
Nothing.new.missing.must_equal(Nothing.new)
|
78
|
-
end
|
79
|
-
end
|
80
|
-
|
81
|
-
describe "#_extract!" do
|
82
|
-
it "raises an exception" do
|
83
|
-
assert_raises(Nothing::AttemptedExtract) {
|
84
|
-
Nothing.new._extract!
|
85
|
-
}
|
86
|
-
end
|
87
|
-
end
|
88
|
-
end
|
89
|
-
|
90
|
-
describe "Integration Specs" do
|
91
|
-
it "works as expected" do
|
92
|
-
Just.new(5).bind { |val|
|
93
|
-
Just.new(val * 3)
|
94
|
-
}.bind { |val|
|
95
|
-
if (val > 10)
|
96
|
-
Nothing.new
|
97
|
-
else
|
98
|
-
Just.new(val) + 1
|
99
|
-
end
|
100
|
-
}.must_equal(Nothing.new)
|
101
|
-
end
|
102
|
-
end
|