fear 0.5.0 → 0.6.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/.rubocop.yml +4 -0
- data/CHANGELOG.md +5 -0
- data/README.md +40 -34
- data/fear.gemspec +2 -1
- data/lib/fear/either.rb +9 -1
- data/lib/fear/failure.rb +2 -2
- data/lib/fear/option.rb +8 -0
- data/lib/fear/right_biased.rb +21 -0
- data/lib/fear/try.rb +6 -7
- data/lib/fear/version.rb +1 -1
- data/spec/fear/failure_spec.rb +1 -1
- data/spec/fear/left_spec.rb +10 -1
- data/spec/fear/none_spec.rb +9 -0
- data/spec/fear/right_biased/right.rb +10 -0
- metadata +22 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6ed9cfc50bd85c7975607f880037044e5bba3aad
|
4
|
+
data.tar.gz: 908994c021e427c5ec6724581f7355a7cf754f39
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e7d901c611b11fc3f90c9c6cd252cb1cb62a1e36bdd1ff825d4412fa5aecd7054de4c3c562bb56b8692130f436c85ab88e81b7247a7ec691895b656de27b4a24
|
7
|
+
data.tar.gz: 1d5b23551ce259c08834b62e1cc0956bf09c7fc31c4d5af56e80b625efe56f079f9f9311216b5c76d5d8cd1dfe64bdf87090c9d393f9e5097cf7a479713dd2a0
|
data/.rubocop.yml
CHANGED
data/CHANGELOG.md
ADDED
data/README.md
CHANGED
@@ -23,9 +23,9 @@ Or install it yourself as:
|
|
23
23
|
|
24
24
|
## Usage
|
25
25
|
|
26
|
-
### Option
|
26
|
+
### Option ([Documentation](http://www.rubydoc.info/github/bolshakov/fear/master/Fear/Option))
|
27
27
|
|
28
|
-
Represents optional values. Instances of `Option` are either an instance of
|
28
|
+
Represents optional (nullable) values. Instances of `Option` are either an instance of
|
29
29
|
`Some` or the object `None`.
|
30
30
|
|
31
31
|
The most idiomatic way to use an `Option` instance is to treat it
|
@@ -34,17 +34,22 @@ as a collection and use `map`, `flat_map`, `select`, or `each`:
|
|
34
34
|
```ruby
|
35
35
|
include Fear::Option::Mixin
|
36
36
|
|
37
|
-
|
38
|
-
|
39
|
-
|
37
|
+
def normalize_name(name)
|
38
|
+
Option(name)
|
39
|
+
.map(&:strip)
|
40
|
+
.select { |n| n.length != 0 }
|
41
|
+
.map(&:upcase)
|
42
|
+
.get_or_else('NONAME')
|
43
|
+
end
|
44
|
+
|
45
|
+
normalize_name('robert paulson ') #=> 'ROBERT PAULSON'
|
46
|
+
normalize_name(nil) #=> 'NONAME'
|
40
47
|
```
|
41
48
|
|
42
49
|
This allows for sophisticated chaining of `Option` values without
|
43
50
|
having to check for the existence of a value.
|
44
51
|
|
45
|
-
|
46
|
-
|
47
|
-
### Try
|
52
|
+
### Try ([Documentation](http://www.rubydoc.info/github/bolshakov/fear/master/Fear/Try))
|
48
53
|
|
49
54
|
The `Try` represents a computation that may either result in an exception,
|
50
55
|
or return a successfully computed value. Instances of `Try`, are either
|
@@ -60,19 +65,17 @@ include Fear::Try::Mixin
|
|
60
65
|
dividend = Try { Integer(params[:dividend]) }
|
61
66
|
divisor = Try { Integer(params[:divisor]) }
|
62
67
|
|
63
|
-
|
68
|
+
result = dividend.flat_map { |x| divisor.map { |y| x / y } }
|
64
69
|
|
65
|
-
if
|
66
|
-
puts "Result of #{dividend.get} / #{divisor.get} is: #{
|
70
|
+
if result.success?
|
71
|
+
puts "Result of #{dividend.get} / #{divisor.get} is: #{result.get}"
|
67
72
|
else
|
68
73
|
puts "You must've divided by zero or entered something wrong. Try again"
|
69
|
-
puts "Info from the exception: #{
|
74
|
+
puts "Info from the exception: #{result.exception.message}"
|
70
75
|
end
|
71
76
|
```
|
72
77
|
|
73
|
-
|
74
|
-
|
75
|
-
### Either
|
78
|
+
### Either ([Documentation](http://www.rubydoc.info/github/bolshakov/fear/master/Fear/Either))
|
76
79
|
|
77
80
|
Represents a value of one of two possible types (a disjoint union.)
|
78
81
|
An instance of `Either` is either an instance of `Left` or `Right`.
|
@@ -102,9 +105,7 @@ puts(
|
|
102
105
|
-> (x) { "You passed me the String: #{x}" }
|
103
106
|
)
|
104
107
|
)
|
105
|
-
```
|
106
|
-
|
107
|
-
See full documentation [Fear::Either](http://www.rubydoc.info/github/bolshakov/fear/master/Fear/Either)
|
108
|
+
```
|
108
109
|
|
109
110
|
### For composition
|
110
111
|
|
@@ -115,31 +116,36 @@ is supported by `For`.
|
|
115
116
|
```ruby
|
116
117
|
include Fear::For::Mixin
|
117
118
|
|
118
|
-
|
119
|
-
|
120
|
-
|
119
|
+
def divide(dividend, divisor)
|
120
|
+
For(x: dividend, y: divisor) do
|
121
|
+
x / y
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
dividend = Try { Integer(params[:dividend]) } #=> Try(4)
|
126
|
+
divisor = Try { Integer(params[:divisor]) } #=> Try(2)
|
127
|
+
|
128
|
+
divide(dividend, divisor) #=> Try(2)
|
121
129
|
```
|
122
130
|
|
123
131
|
It would be translated to
|
124
132
|
|
125
133
|
```ruby
|
126
|
-
|
127
|
-
|
128
|
-
|
134
|
+
Success(4).flat_map do |x|
|
135
|
+
Success(2).map do |y|
|
136
|
+
x / y
|
129
137
|
end
|
130
138
|
end
|
131
139
|
```
|
132
140
|
|
133
|
-
If one of operands is
|
141
|
+
If one of operands is Failure, the result is Failure
|
134
142
|
|
135
143
|
```ruby
|
136
|
-
For(a: Some(2), b: None()) do
|
137
|
-
a * b
|
138
|
-
end #=> None()
|
139
144
|
|
140
|
-
|
141
|
-
|
142
|
-
|
145
|
+
dividend = Try { 42 }
|
146
|
+
divisor = Try { Integer('ehuton') }
|
147
|
+
|
148
|
+
divide(dividend, divisor) #=> Failure(<ArgumentError: invalid value for Integer(): "ehuton">)
|
143
149
|
```
|
144
150
|
|
145
151
|
`For` works with arrays as well
|
@@ -194,9 +200,9 @@ provides a bunch of rspec matchers.
|
|
194
200
|
|
195
201
|
## Alternatives
|
196
202
|
|
197
|
-
* [dry-monads](https://github.com/dry-rb/dry-monads)
|
198
203
|
* [deterministic](https://github.com/pzol/deterministic)
|
199
|
-
* [
|
204
|
+
* [dry-monads](https://github.com/dry-rb/dry-monads)
|
200
205
|
* [kleisli](https://github.com/txus/kleisli)
|
206
|
+
* [maybe](https://github.com/bhb/maybe)
|
207
|
+
* [ruby-possibly](https://github.com/rap1ds/ruby-possibly)
|
201
208
|
* [rumonade](https://github.com/ms-ati/rumonade)
|
202
|
-
|
data/fear.gemspec
CHANGED
@@ -25,6 +25,7 @@ Gem::Specification.new do |spec|
|
|
25
25
|
spec.add_development_dependency 'rake', '~> 10.0'
|
26
26
|
spec.add_development_dependency 'rspec', '~> 3.1'
|
27
27
|
spec.add_development_dependency 'spbtv_code_style'
|
28
|
-
spec.add_development_dependency 'rubocop-rspec'
|
28
|
+
spec.add_development_dependency 'rubocop-rspec', '1.13.0'
|
29
|
+
spec.add_development_dependency 'rubocop', '0.47.1'
|
29
30
|
spec.add_development_dependency 'simplecov'
|
30
31
|
end
|
data/lib/fear/either.rb
CHANGED
@@ -45,6 +45,14 @@ module Fear
|
|
45
45
|
# Right(42).get_or_else(12) #=> 42
|
46
46
|
# Left('undefined').get_or_else(12) #=> 12
|
47
47
|
#
|
48
|
+
# @!method or_else(&alternative)
|
49
|
+
# Returns this +Right+ or the given alternative if this is a +Left+.
|
50
|
+
# @return [Either]
|
51
|
+
# @example
|
52
|
+
# Right(42).or_else { Right(21) } #=> Right(42)
|
53
|
+
# Left('unknown').or_else { Right(21) } #=> Right(21)
|
54
|
+
# Left('unknown').or_else { Left('empty') } #=> Left('empty')
|
55
|
+
#
|
48
56
|
# @!method include?(other_value)
|
49
57
|
# Returns +true+ if +Right+ has an element that is equal
|
50
58
|
# (as determined by +==+) to +other_value+, +false+ otherwise.
|
@@ -206,7 +214,7 @@ module Fear
|
|
206
214
|
# Left("flower").join_right #=> Left("flower")
|
207
215
|
# Left(Right("flower")).join_right #=> Left(Right("flower"))
|
208
216
|
#
|
209
|
-
#
|
217
|
+
# @!method join_right
|
210
218
|
# Joins an +Either+ through +Left+. This method requires
|
211
219
|
# that the left side of this +Either+ is itself an
|
212
220
|
# +Either+ type.
|
data/lib/fear/failure.rb
CHANGED
data/lib/fear/option.rb
CHANGED
@@ -42,6 +42,14 @@ module Fear
|
|
42
42
|
# Some(42).get_or_else(12) #=> 42
|
43
43
|
# None().get_or_else(12) #=> 12
|
44
44
|
#
|
45
|
+
# @!method or_else(&alternative)
|
46
|
+
# Returns this +Some+ or the given alternative if this is a +None+.
|
47
|
+
# @return [Option]
|
48
|
+
# @example
|
49
|
+
# Some(42).or_else { Some(21) } #=> Some(42)
|
50
|
+
# None().or_else { Some(21) } #=> Some(21)
|
51
|
+
# None().or_else { None() } #=> None()
|
52
|
+
#
|
45
53
|
# @!method include?(other_value)
|
46
54
|
# Returns +true+ if it has an element that is equal
|
47
55
|
# (as determined by +==+) to +other_value+, +false+ otherwise.
|
data/lib/fear/right_biased.rb
CHANGED
@@ -11,6 +11,15 @@ module Fear
|
|
11
11
|
super
|
12
12
|
end
|
13
13
|
|
14
|
+
# Returns this `RightBiased::Right` or the given alternative if
|
15
|
+
# this is a `RightBiased::Left`.
|
16
|
+
def or_else(*args, &block)
|
17
|
+
Utils.assert_arg_or_block!('or_else', *args, &block)
|
18
|
+
super.tap do |result|
|
19
|
+
Utils.assert_type!(result, left_class, right_class)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
14
23
|
def flat_map
|
15
24
|
super.tap do |result|
|
16
25
|
Utils.assert_type!(result, left_class, right_class)
|
@@ -43,6 +52,11 @@ module Fear
|
|
43
52
|
value
|
44
53
|
end
|
45
54
|
|
55
|
+
# @return [self]
|
56
|
+
def or_else
|
57
|
+
self
|
58
|
+
end
|
59
|
+
|
46
60
|
# @param [any]
|
47
61
|
# @return [Boolean]
|
48
62
|
def include?(other_value)
|
@@ -112,6 +126,13 @@ module Fear
|
|
112
126
|
args.fetch(0) { yield }
|
113
127
|
end
|
114
128
|
|
129
|
+
# @!method get_or_else(&alternative)
|
130
|
+
# @return [RightBiased] result of evaluating a block.
|
131
|
+
#
|
132
|
+
def or_else(*_args)
|
133
|
+
yield
|
134
|
+
end
|
135
|
+
|
115
136
|
# @param [any]
|
116
137
|
# @return [false]
|
117
138
|
#
|
data/lib/fear/try.rb
CHANGED
@@ -13,7 +13,7 @@ module Fear
|
|
13
13
|
#
|
14
14
|
# dividend = Try { Integer(params[:dividend]) }
|
15
15
|
# divisor = Try { Integer(params[:divisor]) }
|
16
|
-
# problem = dividend.flat_map { |x| divisor.map { |y| x / y }
|
16
|
+
# problem = dividend.flat_map { |x| divisor.map { |y| x / y } }
|
17
17
|
#
|
18
18
|
# if problem.success?
|
19
19
|
# puts "Result of #{dividend.get} / #{divisor.get} is: #{problem.get}"
|
@@ -144,14 +144,13 @@ module Fear
|
|
144
144
|
# Success(42).get #=> 42
|
145
145
|
# Failure(ArgumentError.new).get #=> ArgumentError: ArgumentError
|
146
146
|
#
|
147
|
-
# @!method or_else(&
|
148
|
-
# Returns this +Try+ if it's a +Success+ or the given
|
149
|
-
# argument if this is a +Failure+.
|
147
|
+
# @!method or_else(&alternative)
|
148
|
+
# Returns this +Try+ if it's a +Success+ or the given alternative if this is a +Failure+.
|
150
149
|
# @return [Try]
|
151
150
|
# @example
|
152
|
-
# Success(42).or_else { -1 } #=> Success(42)
|
153
|
-
# Failure(ArgumentError.new).or_else { -1 } #=> Success(-1)
|
154
|
-
# Failure(ArgumentError.new).or_else { 1/0 } #=> Failure(ZeroDivisionError.new('divided by 0'))
|
151
|
+
# Success(42).or_else { Success(-1) } #=> Success(42)
|
152
|
+
# Failure(ArgumentError.new).or_else { Success(-1) } #=> Success(-1)
|
153
|
+
# Failure(ArgumentError.new).or_else { Try { 1/0 } } #=> Failure(ZeroDivisionError.new('divided by 0'))
|
155
154
|
#
|
156
155
|
# @!method flatten
|
157
156
|
# Transforms a nested +Try+, ie, a +Success+ of +Success+,
|
data/lib/fear/version.rb
CHANGED
data/spec/fear/failure_spec.rb
CHANGED
@@ -28,7 +28,7 @@ RSpec.describe Fear::Failure do
|
|
28
28
|
|
29
29
|
describe '#or_else' do
|
30
30
|
context 'default does not fail' do
|
31
|
-
subject { failure.or_else { 'value' } }
|
31
|
+
subject { failure.or_else { Fear::Success.new('value') } }
|
32
32
|
it { is_expected.to eq(Fear::Success.new('value')) }
|
33
33
|
end
|
34
34
|
|
data/spec/fear/left_spec.rb
CHANGED
@@ -39,6 +39,15 @@ RSpec.describe Fear::Left do
|
|
39
39
|
end
|
40
40
|
end
|
41
41
|
|
42
|
+
describe '#or_else' do
|
43
|
+
subject { left.or_else { alternative } }
|
44
|
+
let(:alternative) { Left(42) }
|
45
|
+
|
46
|
+
it 'returns alternative' do
|
47
|
+
is_expected.to eq(alternative)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
42
51
|
describe '#select' do
|
43
52
|
subject do
|
44
53
|
left.select { |v| v == 'value' }
|
@@ -95,7 +104,7 @@ RSpec.describe Fear::Left do
|
|
95
104
|
let(:either) { described_class.new(value) }
|
96
105
|
let(:value) { Left('error') }
|
97
106
|
|
98
|
-
it '
|
107
|
+
it 'returns value' do
|
99
108
|
is_expected.to eq(Left('error'))
|
100
109
|
end
|
101
110
|
end
|
data/spec/fear/none_spec.rb
CHANGED
@@ -17,6 +17,15 @@ RSpec.describe Fear::None do
|
|
17
17
|
it { is_expected.to eq(nil) }
|
18
18
|
end
|
19
19
|
|
20
|
+
describe '#or_else' do
|
21
|
+
subject { none.or_else { alternative } }
|
22
|
+
let(:alternative) { Some(42) }
|
23
|
+
|
24
|
+
it 'returns alternative' do
|
25
|
+
is_expected.to eq(alternative)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
20
29
|
describe '#empty?' do
|
21
30
|
subject { none.empty? }
|
22
31
|
it { is_expected.to eq(true) }
|
@@ -41,6 +41,16 @@ RSpec.shared_examples Fear::RightBiased::Right do
|
|
41
41
|
end
|
42
42
|
end
|
43
43
|
|
44
|
+
describe '#or_else' do
|
45
|
+
it 'does not call block' do
|
46
|
+
expect { |probe| right.or_else(&probe) }.not_to yield_control
|
47
|
+
end
|
48
|
+
|
49
|
+
it 'returns the same object' do
|
50
|
+
expect(right.or_else { 42 }).to eql(right)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
44
54
|
describe '#map' do
|
45
55
|
subject { right.map(&:length) }
|
46
56
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: fear
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.6.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Tema Bolshakov
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2017-05-04 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: dry-equalizer
|
@@ -84,16 +84,30 @@ dependencies:
|
|
84
84
|
name: rubocop-rspec
|
85
85
|
requirement: !ruby/object:Gem::Requirement
|
86
86
|
requirements:
|
87
|
-
- -
|
87
|
+
- - '='
|
88
88
|
- !ruby/object:Gem::Version
|
89
|
-
version:
|
89
|
+
version: 1.13.0
|
90
90
|
type: :development
|
91
91
|
prerelease: false
|
92
92
|
version_requirements: !ruby/object:Gem::Requirement
|
93
93
|
requirements:
|
94
|
-
- -
|
94
|
+
- - '='
|
95
95
|
- !ruby/object:Gem::Version
|
96
|
-
version:
|
96
|
+
version: 1.13.0
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: rubocop
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - '='
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: 0.47.1
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - '='
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: 0.47.1
|
97
111
|
- !ruby/object:Gem::Dependency
|
98
112
|
name: simplecov
|
99
113
|
requirement: !ruby/object:Gem::Requirement
|
@@ -120,6 +134,7 @@ files:
|
|
120
134
|
- ".rubocop.yml"
|
121
135
|
- ".travis.yml"
|
122
136
|
- ".yardopts"
|
137
|
+
- CHANGELOG.md
|
123
138
|
- Gemfile
|
124
139
|
- LICENSE.txt
|
125
140
|
- README.md
|
@@ -172,7 +187,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
172
187
|
version: '0'
|
173
188
|
requirements: []
|
174
189
|
rubyforge_project:
|
175
|
-
rubygems_version: 2.
|
190
|
+
rubygems_version: 2.6.10
|
176
191
|
signing_key:
|
177
192
|
specification_version: 4
|
178
193
|
summary: "%q{Ruby port of some Scala's monads.}"
|