fear 0.5.0 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 79938c2515814ea5906a6ddba5c880b3ba7f8f57
4
- data.tar.gz: 5393d7b3acf1714ccfa95db7dc2b3d947b49c7dc
3
+ metadata.gz: 6ed9cfc50bd85c7975607f880037044e5bba3aad
4
+ data.tar.gz: 908994c021e427c5ec6724581f7355a7cf754f39
5
5
  SHA512:
6
- metadata.gz: 18f67b3306834c6d5fdbfc698eab233252855c3d0d0e1425f8eabe0e5489a25171c96584491f23d529b6d134cd829f6f4d6ffb0059d6a1f5a959772afecf90e5
7
- data.tar.gz: 404f270b34607bd5ba35d1ced38c9a130a98c8aee0d0dd6d2e5a2118f434d3d00c24489e5b736851fc89fc91ecfff33cef9db31ad889db59443689c9e778746d
6
+ metadata.gz: e7d901c611b11fc3f90c9c6cd252cb1cb62a1e36bdd1ff825d4412fa5aecd7054de4c3c562bb56b8692130f436c85ab88e81b7247a7ec691895b656de27b4a24
7
+ data.tar.gz: 1d5b23551ce259c08834b62e1cc0956bf09c7fc31c4d5af56e80b625efe56f079f9f9311216b5c76d5d8cd1dfe64bdf87090c9d393f9e5097cf7a479713dd2a0
@@ -9,3 +9,7 @@ Style/Documentation:
9
9
 
10
10
  Style/CaseEquality:
11
11
  Enabled: false
12
+
13
+ Metrics/BlockLength:
14
+ Exclude:
15
+ - spec/**/*
@@ -0,0 +1,5 @@
1
+ ## 0.6.0
2
+
3
+ * Added `Either#or_else` and `Option#or_else`. `Try#or_else` may accept only block ([@bolshakov][])
4
+
5
+ [@bolshakov]: https://github.com/bolshakov
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
- name = Option(params[:name])
38
- upper = name.map(&:strip).select { |n| n.length != 0 }.map(&:upcase)
39
- puts upper.get_or_else('')
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
- See full documentation [Fear::Option](http://www.rubydoc.info/github/bolshakov/fear/master/Fear/Option)
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
- problem = dividend.flat_map { |x| divisor.map { |y| x / y }
68
+ result = dividend.flat_map { |x| divisor.map { |y| x / y } }
64
69
 
65
- if problem.success?
66
- puts "Result of #{dividend.get} / #{divisor.get} is: #{problem.get}"
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: #{problem.exception.message}"
74
+ puts "Info from the exception: #{result.exception.message}"
70
75
  end
71
76
  ```
72
77
 
73
- See full documentation [Fear::Try](http://www.rubydoc.info/github/bolshakov/fear/master/Fear/Try)
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
- For(a: Some(2), b: Some(3)) do
119
- a * b
120
- end #=> Some(6)
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
- Some(2).flat_map do |a|
127
- Some(3).map do |b|
128
- a * b
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 None, the result is None
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
- For(a: None(), b: Some(2)) do
141
- a * b
142
- end #=> None()
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
- * [ruby-possibly](https://github.com/rap1ds/ruby-possibly)
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
-
@@ -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
@@ -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
- # # @!method join_right
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.
@@ -27,8 +27,8 @@ module Fear
27
27
  end
28
28
 
29
29
  # @return [Try] of calling block
30
- def or_else
31
- Success.new(yield)
30
+ def or_else(*args)
31
+ super
32
32
  rescue => error
33
33
  Failure.new(error)
34
34
  end
@@ -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.
@@ -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
  #
@@ -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(&default)
148
- # Returns this +Try+ if it's a +Success+ or the given default
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+,
@@ -1,3 +1,3 @@
1
1
  module Fear
2
- VERSION = '0.5.0'.freeze
2
+ VERSION = '0.6.0'.freeze
3
3
  end
@@ -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
 
@@ -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 'it returns value' do
107
+ it 'returns value' do
99
108
  is_expected.to eq(Left('error'))
100
109
  end
101
110
  end
@@ -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.5.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: 2016-12-25 00:00:00.000000000 Z
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: '0'
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: '0'
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.5.1
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.}"