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 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.}"