fear 0.1.0 → 0.2.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/.yardopts +1 -0
- data/README.md +8 -0
- data/fear.gemspec +1 -1
- data/lib/fear/either.rb +192 -97
- data/lib/fear/failure.rb +15 -7
- data/lib/fear/for.rb +22 -7
- data/lib/fear/left.rb +21 -20
- data/lib/fear/none.rb +15 -6
- data/lib/fear/option.rb +123 -40
- data/lib/fear/right.rb +25 -20
- data/lib/fear/right_biased.rb +5 -9
- data/lib/fear/some.rb +13 -8
- data/lib/fear/success.rb +16 -11
- data/lib/fear/try.rb +203 -66
- data/lib/fear/utils.rb +1 -0
- data/lib/fear/version.rb +1 -1
- data/spec/fear/failure_spec.rb +7 -1
- data/spec/fear/left_spec.rb +12 -2
- data/spec/fear/none_spec.rb +10 -7
- data/spec/fear/option_spec.rb +7 -24
- data/spec/fear/right_spec.rb +16 -2
- data/spec/fear/some_spec.rb +11 -7
- data/spec/fear/success_spec.rb +5 -0
- metadata +4 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b856c96f41e1cab50482a618c021f32eccd16d97
|
4
|
+
data.tar.gz: 7e443f61c506e29e1578f64e7f2237664c1465ec
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: fef37c2dd16a69752985bd04d734ab27a69513e9db7a114c93dfb66116473d549e3a3106a0221e1f1e61ad0fa1192291cfb9e76eb7fbfc5af7297540d167610c
|
7
|
+
data.tar.gz: ff910daab541a9279e7838a971db37d9a37f6bdb220e6b17e985a9e3daaebd61cbba31167efc3e1d7b9201958310270b9788597ecc284b61f0f30bf20586e8f6
|
data/.yardopts
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--no-private
|
data/README.md
CHANGED
@@ -32,6 +32,8 @@ The most idiomatic way to use an `Option` instance is to treat it
|
|
32
32
|
as a collection and use `map`, `flat_map`, `select`, or `each`:
|
33
33
|
|
34
34
|
```ruby
|
35
|
+
include Fear::Option::Mixin
|
36
|
+
|
35
37
|
name = Option(params[:name])
|
36
38
|
upper = name.map(&:strip).select { |n| n.length != 0 }.map(&:upcase)
|
37
39
|
puts upper.get_or_else('')
|
@@ -53,6 +55,8 @@ without the need to do explicit exception-handling in all of the places
|
|
53
55
|
that an exception might occur.
|
54
56
|
|
55
57
|
```ruby
|
58
|
+
include Fear::Try::Mixin
|
59
|
+
|
56
60
|
dividend = Try { Integer(params[:dividend]) }
|
57
61
|
divisor = Try { Integer(params[:divisor]) }
|
58
62
|
|
@@ -83,6 +87,8 @@ For example, you could use `Either<String, Fixnum>` to select whether a
|
|
83
87
|
received input is a `String` or an `Fixnum`.
|
84
88
|
|
85
89
|
```ruby
|
90
|
+
include Fear::Either::Mixin
|
91
|
+
|
86
92
|
input = Readline.readline('Type Either a string or an Int: ', true)
|
87
93
|
result = begin
|
88
94
|
Right(Integer(input))
|
@@ -107,6 +113,8 @@ It supports two such operations - `flat_map` and `map`. Any class providing them
|
|
107
113
|
is supported by `For`.
|
108
114
|
|
109
115
|
```ruby
|
116
|
+
include Fear::For::Mixin
|
117
|
+
|
110
118
|
For(a: Some(2), b: Some(3)) do
|
111
119
|
a * b
|
112
120
|
end #=> Some(6)
|
data/fear.gemspec
CHANGED
@@ -11,7 +11,7 @@ Gem::Specification.new do |spec|
|
|
11
11
|
spec.email = ['abolshakov@spbtv.com']
|
12
12
|
spec.summary = "%q{Ruby port of some Scala's monads.}"
|
13
13
|
spec.description = "Ruby port of some Scala's monads."
|
14
|
-
spec.homepage = 'https://github.com/bolshakov/
|
14
|
+
spec.homepage = 'https://github.com/bolshakov/fear'
|
15
15
|
spec.license = 'MIT'
|
16
16
|
|
17
17
|
spec.files = `git ls-files -z`.split("\x0")
|
data/lib/fear/either.rb
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
module Fear
|
2
2
|
# Represents a value of one of two possible types (a disjoint union.)
|
3
|
-
# An instance of
|
3
|
+
# An instance of +Either+ is either an instance of +Left+ or +Right+.
|
4
4
|
#
|
5
|
-
# A common use of
|
6
|
-
# with possible missing values. In this usage,
|
7
|
-
# with a
|
8
|
-
#
|
9
|
-
# that
|
5
|
+
# A common use of +Either+ is as an alternative to +Option+ for dealing
|
6
|
+
# with possible missing values. In this usage, +None+ is replaced
|
7
|
+
# with a +Left+ which can contain useful information.
|
8
|
+
# +Right+ takes the place of +Some+. Convention dictates
|
9
|
+
# that +Left+ is used for failure and +Right+ is used for Right.
|
10
10
|
#
|
11
|
-
# For example, you could use
|
12
|
-
# received input is a
|
11
|
+
# For example, you could use +Either<String, Fixnum>+ to select_or_else whether a
|
12
|
+
# received input is a +String+ or an +Fixnum+.
|
13
13
|
#
|
14
14
|
# @example
|
15
15
|
# in = Readline.readline('Type Either a string or an Int: ', true)
|
@@ -26,96 +26,198 @@ module Fear
|
|
26
26
|
# )
|
27
27
|
# )
|
28
28
|
#
|
29
|
-
# Either is right-biased, which means that
|
30
|
-
# operate on. If it is
|
29
|
+
# Either is right-biased, which means that +Right+ is assumed to be the default case to
|
30
|
+
# operate on. If it is +Left+, operations like +#map+, +#flat_map+, ... return the +Left+ value
|
31
31
|
# unchanged:
|
32
32
|
#
|
33
|
-
#
|
34
|
-
#
|
35
|
-
#
|
36
|
-
#
|
37
|
-
#
|
38
|
-
#
|
39
|
-
#
|
40
|
-
#
|
41
|
-
#
|
42
|
-
#
|
43
|
-
#
|
44
|
-
#
|
45
|
-
#
|
46
|
-
#
|
47
|
-
#
|
48
|
-
#
|
49
|
-
# Right
|
50
|
-
#
|
51
|
-
#
|
52
|
-
#
|
53
|
-
#
|
54
|
-
#
|
55
|
-
#
|
56
|
-
#
|
57
|
-
#
|
58
|
-
#
|
59
|
-
#
|
60
|
-
#
|
61
|
-
#
|
62
|
-
#
|
63
|
-
#
|
64
|
-
#
|
65
|
-
#
|
66
|
-
#
|
67
|
-
#
|
68
|
-
#
|
69
|
-
#
|
70
|
-
#
|
71
|
-
#
|
72
|
-
#
|
73
|
-
# Right
|
74
|
-
#
|
75
|
-
#
|
76
|
-
#
|
77
|
-
#
|
78
|
-
#
|
79
|
-
#
|
80
|
-
#
|
81
|
-
#
|
82
|
-
#
|
83
|
-
#
|
84
|
-
#
|
85
|
-
#
|
86
|
-
#
|
87
|
-
#
|
88
|
-
#
|
89
|
-
#
|
90
|
-
#
|
91
|
-
#
|
92
|
-
#
|
93
|
-
#
|
94
|
-
#
|
33
|
+
# @!method get_or_else(*args)
|
34
|
+
# Returns the value from this +Right+ or evaluates the given
|
35
|
+
# default argument if this is a +Left+.
|
36
|
+
# @overload get_or_else(&default)
|
37
|
+
# @yieldreturn [any]
|
38
|
+
# @return [any]
|
39
|
+
# @example
|
40
|
+
# Right(42).get_or_else { 24/2 } #=> 42
|
41
|
+
# Left('undefined').get_or_else { 24/2 } #=> 12
|
42
|
+
# @overload get_or_else(default)
|
43
|
+
# @return [any]
|
44
|
+
# @example
|
45
|
+
# Right(42).get_or_else(12) #=> 42
|
46
|
+
# Left('undefined').get_or_else(12) #=> 12
|
47
|
+
#
|
48
|
+
# @!method include?(other_value)
|
49
|
+
# Returns +true+ if +Right+ has an element that is equal
|
50
|
+
# (as determined by +==+) to +other_value+, +false+ otherwise.
|
51
|
+
# @param [any]
|
52
|
+
# @return [Boolean]
|
53
|
+
# @example
|
54
|
+
# Right(17).include?(17) #=> true
|
55
|
+
# Right(17).include?(7) #=> false
|
56
|
+
# Left('undefined').include?(17) #=> false
|
57
|
+
#
|
58
|
+
# @!method each(&block)
|
59
|
+
# Performs the given block if this is a +Right+.
|
60
|
+
# @yieldparam [any] value
|
61
|
+
# @yieldreturn [void]
|
62
|
+
# @return [Option] itself
|
63
|
+
# @example
|
64
|
+
# Right(17).each do |value|
|
65
|
+
# puts value
|
66
|
+
# end #=> prints 17
|
67
|
+
#
|
68
|
+
# Left('undefined').each do |value|
|
69
|
+
# puts value
|
70
|
+
# end #=> does nothing
|
71
|
+
#
|
72
|
+
# @!method map(&block)
|
73
|
+
# Maps the given block to the value from this +Right+ or
|
74
|
+
# returns this if this is a +Left+.
|
75
|
+
# @yieldparam [any] value
|
76
|
+
# @yieldreturn [any]
|
77
|
+
# @example
|
78
|
+
# Right(42).map { |v| v/2 } #=> Right(21)
|
79
|
+
# Left('undefined').map { |v| v/2 } #=> Left('undefined')
|
80
|
+
#
|
81
|
+
# @!method flat_map(&block)
|
82
|
+
# Returns the given block applied to the value from this +Right+
|
83
|
+
# or returns this if this is a +Left+.
|
84
|
+
# @yieldparam [any] value
|
85
|
+
# @yieldreturn [Option]
|
86
|
+
# @return [Option]
|
87
|
+
# @example
|
88
|
+
# Right(42).flat_map { |v| Right(v/2) } #=> Right(21)
|
89
|
+
# Left('undefined').flat_map { |v| Right(v/2) } #=> Left('undefined')
|
90
|
+
#
|
91
|
+
# @!method to_a
|
92
|
+
# Returns an +Array+ containing the +Right+ value or an
|
93
|
+
# empty +Array+ if this is a +Left+.
|
94
|
+
# @return [Array]
|
95
|
+
# @example
|
96
|
+
# Right(42).to_a #=> [21]
|
97
|
+
# Left('undefined').to_a #=> []
|
98
|
+
#
|
99
|
+
# @!method to_option
|
100
|
+
# Returns an +Some+ containing the +Right+ value or a +None+ if
|
101
|
+
# this is a +Left+.
|
102
|
+
# @return [Option]
|
103
|
+
# @example
|
104
|
+
# Right(42).to_option #=> Some(21)
|
105
|
+
# Left('undefined').to_option #=> None()
|
106
|
+
#
|
107
|
+
# @!method any?(&predicate)
|
108
|
+
# Returns +false+ if +Left+ or returns the result of the
|
109
|
+
# application of the given predicate to the +Right+ value.
|
110
|
+
# @yieldparam [any] value
|
111
|
+
# @yieldreturn [Boolean]
|
112
|
+
# @return [Boolean]
|
113
|
+
# @example
|
114
|
+
# Right(12).any?( |v| v > 10) #=> true
|
115
|
+
# Right(7).any?( |v| v > 10) #=> false
|
116
|
+
# Left('undefined').any?( |v| v > 10) #=> false
|
117
|
+
#
|
118
|
+
# -----
|
119
|
+
#
|
120
|
+
# @!method right?
|
121
|
+
# Returns +true+ if this is a +Right+, +false+ otherwise.
|
122
|
+
# @note this method is also aliased as +#success?+
|
123
|
+
# @return [Boolean]
|
124
|
+
# @example
|
125
|
+
# Right(42).right? #=> true
|
126
|
+
# Left('err').right? #=> false
|
127
|
+
#
|
128
|
+
# @!method left?
|
129
|
+
# Returns +true+ if this is a +Left+, +false+ otherwise.
|
130
|
+
# @note this method is also aliased as +#failure?+
|
131
|
+
# @return [Boolean]
|
132
|
+
# @example
|
133
|
+
# Right(42).left? #=> false
|
134
|
+
# Left('err').left? #=> true
|
135
|
+
#
|
136
|
+
# @!method select_or_else(default, &predicate)
|
137
|
+
# Returns +Left+ of the default if the given predicate
|
138
|
+
# does not hold for the right value, otherwise, returns +Right+.
|
139
|
+
# @param default [Object, Proc]
|
140
|
+
# @yieldparam value [Object]
|
141
|
+
# @yieldreturn [Boolean]
|
142
|
+
# @return [Either]
|
143
|
+
# @example
|
144
|
+
# Right(12).select_or_else(-1, &:even?) #=> Right(12)
|
145
|
+
# Right(7).select_or_else(-1, &:even?) #=> Left(-1)
|
146
|
+
# Left(12).select_or_else(-1, &:even?) #=> Left(-1)
|
147
|
+
# Left(12).select_or_else(-> { -1 }, &:even?) #=> Left(-1)
|
148
|
+
#
|
149
|
+
# @!method select(&predicate)
|
150
|
+
# Returns +Left+ of value if the given predicate
|
151
|
+
# does not hold for the right value, otherwise, returns +Right+.
|
152
|
+
# @yieldparam value [Object]
|
153
|
+
# @yieldreturn [Boolean]
|
154
|
+
# @return [Either]
|
155
|
+
# @example
|
156
|
+
# Right(12).select(&:even?) #=> Right(12)
|
157
|
+
# Right(7).select(&:even?) #=> Left(7)
|
158
|
+
# Left(12).select(&:even?) #=> Left(12)
|
159
|
+
# Left(7).select(&:even?) #=> Left(7)
|
160
|
+
#
|
161
|
+
# @!method swap
|
162
|
+
# If this is a +Left+, then return the left value in +Right+ or vice versa.
|
163
|
+
# @return [Either]
|
164
|
+
# @example
|
165
|
+
# Left('left').swap #=> Right('left')
|
166
|
+
# Right('right').swap #=> Light('left')
|
167
|
+
#
|
168
|
+
# @!method reduce(reduce_left, reduce_right)
|
169
|
+
# Applies +reduce_left+ if this is a +Left+ or +reduce_right+ if
|
170
|
+
# this is a +Right+.
|
171
|
+
# @param reduce_left [Proc] the Proc to apply if this is a +Left+
|
172
|
+
# @param reduce_right [Proc] the Proc to apply if this is a +Right+
|
173
|
+
# @return [any] the results of applying the Proc
|
174
|
+
# @example
|
175
|
+
# result = possibly_failing_operation()
|
176
|
+
# log(
|
177
|
+
# result.reduce(
|
178
|
+
# ->(ex) { "Operation failed with #{ex}" },
|
179
|
+
# ->(v) { "Operation produced value: #{v}" },
|
180
|
+
# )
|
95
181
|
# )
|
96
|
-
# )
|
97
182
|
#
|
98
|
-
# @example #join_right
|
99
|
-
# Right(Right(12)).join_right #=> Right(12)
|
100
|
-
# Right(Left("flower")).join_right #=> Left("flower")
|
101
|
-
# Left("flower").join_right #=> Left("flower")
|
102
|
-
# Left(Right("flower")).join_right #=> Left(Right("flower"))
|
103
183
|
#
|
104
|
-
#
|
105
|
-
#
|
106
|
-
#
|
107
|
-
#
|
108
|
-
#
|
184
|
+
# @!method join_right
|
185
|
+
# Joins an +Either+ through +Right+. This method requires
|
186
|
+
# that the right side of this +Either+ is itself an
|
187
|
+
# +Either+ type.
|
188
|
+
# @note This method, and +join_left+, are analogous to +Option#flatten+
|
189
|
+
# @return [Either]
|
190
|
+
# @raise [TypeError] if it does not contain +Either+.
|
191
|
+
# @example
|
192
|
+
# Right(Right(12)).join_right #=> Right(12)
|
193
|
+
# Right(Left("flower")).join_right #=> Left("flower")
|
194
|
+
# Left("flower").join_right #=> Left("flower")
|
195
|
+
# Left(Right("flower")).join_right #=> Left(Right("flower"))
|
196
|
+
#
|
197
|
+
# # @!method join_right
|
198
|
+
# Joins an +Either+ through +Left+. This method requires
|
199
|
+
# that the left side of this +Either+ is itself an
|
200
|
+
# +Either+ type.
|
201
|
+
# @note This method, and +join_right+, are analogous to +Option#flatten+
|
202
|
+
# @return [Either]
|
203
|
+
# @raise [TypeError] if it does not contain +Either+.
|
204
|
+
# @example
|
205
|
+
# Left(Right("flower")).join_left #=> Right("flower")
|
206
|
+
# Left(Left(12)).join_left #=> Left(12)
|
207
|
+
# Right("daisy").join_left #=> Right("daisy")
|
208
|
+
# Right(Left("daisy")).join_left #=> Right(Left("daisy"))
|
109
209
|
#
|
110
210
|
# @see https://github.com/scala/scala/blob/2.12.x/src/library/scala/util/Either.scala
|
111
211
|
#
|
112
212
|
module Either
|
113
213
|
include Dry::Equalizer(:value)
|
114
214
|
|
215
|
+
# @private
|
115
216
|
def left_class
|
116
217
|
Left
|
117
218
|
end
|
118
219
|
|
220
|
+
# @private
|
119
221
|
def right_class
|
120
222
|
Right
|
121
223
|
end
|
@@ -124,23 +226,16 @@ module Fear
|
|
124
226
|
@value = value
|
125
227
|
end
|
126
228
|
|
127
|
-
# @return [Boolean]
|
128
|
-
def right?
|
129
|
-
is_a?(Right)
|
130
|
-
end
|
131
|
-
|
132
|
-
alias success? right?
|
133
|
-
|
134
|
-
# @return [Boolean]
|
135
|
-
def left?
|
136
|
-
!right?
|
137
|
-
end
|
138
|
-
|
139
|
-
alias failure? left?
|
140
|
-
|
141
229
|
attr_reader :value
|
142
230
|
protected :value
|
143
231
|
|
232
|
+
# Include this mixin to access convenient factory methods.
|
233
|
+
# @example
|
234
|
+
# include Fear::Either::Mixin
|
235
|
+
#
|
236
|
+
# Right('flower') #=> #<Fear::Right value='flower'>
|
237
|
+
# Left('beaf') #=> #<Fear::Legt value='beaf'>
|
238
|
+
#
|
144
239
|
module Mixin
|
145
240
|
# @param [any]
|
146
241
|
# @return [Left]
|
data/lib/fear/failure.rb
CHANGED
@@ -4,6 +4,7 @@ module Fear
|
|
4
4
|
include Dry::Equalizer(:value)
|
5
5
|
include RightBiased::Left
|
6
6
|
|
7
|
+
# @param [StandardError]
|
7
8
|
def initialize(exception)
|
8
9
|
@value = exception
|
9
10
|
end
|
@@ -11,10 +12,17 @@ module Fear
|
|
11
12
|
attr_reader :value
|
12
13
|
protected :value
|
13
14
|
|
15
|
+
# @return [Boolean]
|
14
16
|
def success?
|
15
17
|
false
|
16
18
|
end
|
17
19
|
|
20
|
+
# @return [true]
|
21
|
+
def failure?
|
22
|
+
true
|
23
|
+
end
|
24
|
+
|
25
|
+
# @raise
|
18
26
|
def get
|
19
27
|
fail value
|
20
28
|
end
|
@@ -36,13 +44,9 @@ module Fear
|
|
36
44
|
self
|
37
45
|
end
|
38
46
|
|
39
|
-
# Applies the given block to exception.
|
40
|
-
# This is like `flat_map` for the exception.
|
41
|
-
#
|
42
47
|
# @yieldparam [Exception]
|
43
48
|
# @yieldreturn [Try]
|
44
49
|
# @return [Try]
|
45
|
-
#
|
46
50
|
def recover_with
|
47
51
|
yield(value).tap do |result|
|
48
52
|
Utils.assert_type!(result, Success, Failure)
|
@@ -51,14 +55,18 @@ module Fear
|
|
51
55
|
Failure.new(error)
|
52
56
|
end
|
53
57
|
|
54
|
-
#
|
55
|
-
#
|
58
|
+
# @yieldparam [Exception]
|
59
|
+
# @yieldreturn [any]
|
56
60
|
# @return [Try]
|
57
|
-
#
|
58
61
|
def recover
|
59
62
|
Success.new(yield(value))
|
60
63
|
rescue => error
|
61
64
|
Failure.new(error)
|
62
65
|
end
|
66
|
+
|
67
|
+
# @return [Left]
|
68
|
+
def to_either
|
69
|
+
Left.new(value)
|
70
|
+
end
|
63
71
|
end
|
64
72
|
end
|
data/lib/fear/for.rb
CHANGED
@@ -1,14 +1,15 @@
|
|
1
1
|
module Fear
|
2
2
|
# This class provides syntactic sugar for composition of
|
3
3
|
# multiple monadic operations. It supports two such
|
4
|
-
# operations -
|
5
|
-
# is supported by
|
4
|
+
# operations - +flat_map+ and +map+. Any class providing them
|
5
|
+
# is supported by +For+.
|
6
6
|
#
|
7
|
-
#
|
8
|
-
#
|
9
|
-
#
|
10
|
-
#
|
11
|
-
#
|
7
|
+
# For(a: Some(2), b: Some(3)) { a * b } #=> Some(6)
|
8
|
+
#
|
9
|
+
# If one of operands is None, the result is None
|
10
|
+
#
|
11
|
+
# For(a: Some(2), b: None()) { a * b } #=> None()
|
12
|
+
# For(a: None(), b: Some(2)) { a * b } #=> None()
|
12
13
|
#
|
13
14
|
# Lets look at first example:
|
14
15
|
#
|
@@ -71,6 +72,7 @@ module Fear
|
|
71
72
|
@variables = variables
|
72
73
|
end
|
73
74
|
attr_reader :variables
|
75
|
+
private :variables
|
74
76
|
|
75
77
|
def call(&block)
|
76
78
|
variable_name_and_monad, *tail = *variables
|
@@ -92,6 +94,19 @@ module Fear
|
|
92
94
|
end
|
93
95
|
end
|
94
96
|
|
97
|
+
# Include this mixin to access convenient factory method for +For+.
|
98
|
+
# @example
|
99
|
+
# include Fear::For::Mixin
|
100
|
+
#
|
101
|
+
# For(a: Some(2), b: Some(3)) { a * b } #=> Some(6)
|
102
|
+
# For(a: Some(2), b: None()) { a * b } #=> None()
|
103
|
+
#
|
104
|
+
# For(a: Right(2), b: Right(3)) { a * b } #=> Right(6)
|
105
|
+
# For(a: Right(2), b: Left(3)) { a * b } #=> Left(3)
|
106
|
+
#
|
107
|
+
# For(a: Success(2), b: Success(3)) { a * b } #=> Success(3)
|
108
|
+
# For(a: Success(2), b: Failure(...)) { a * b } #=> Failure(...)
|
109
|
+
#
|
95
110
|
module Mixin
|
96
111
|
# @param locals [Hash{Symbol => {#map, #flat_map}}]
|
97
112
|
# @return [{#map, #flat_map}]
|
data/lib/fear/left.rb
CHANGED
@@ -3,46 +3,47 @@ module Fear
|
|
3
3
|
include Either
|
4
4
|
include RightBiased::Left
|
5
5
|
|
6
|
-
#
|
7
|
-
|
6
|
+
# @return [false]
|
7
|
+
def right?
|
8
|
+
false
|
9
|
+
end
|
10
|
+
alias success? right?
|
11
|
+
|
12
|
+
# @return [true]
|
13
|
+
def left?
|
14
|
+
true
|
15
|
+
end
|
16
|
+
alias failure? left?
|
17
|
+
|
8
18
|
# @param default [Proc, any]
|
9
19
|
# @return [Either]
|
10
|
-
|
11
|
-
def select(default)
|
20
|
+
def select_or_else(default)
|
12
21
|
Left.new(Utils.return_or_call_proc(default))
|
13
22
|
end
|
14
23
|
|
24
|
+
# @return [Left]
|
25
|
+
def select
|
26
|
+
self
|
27
|
+
end
|
28
|
+
|
15
29
|
# @return [Right] value in `Right`
|
16
|
-
#
|
17
30
|
def swap
|
18
31
|
Right.new(value)
|
19
32
|
end
|
20
33
|
|
21
|
-
# @param reduce_left [Proc]
|
22
|
-
# @return [any]
|
23
|
-
#
|
34
|
+
# @param reduce_left [Proc]
|
35
|
+
# @return [any]
|
24
36
|
def reduce(reduce_left, _)
|
25
37
|
reduce_left.call(value)
|
26
38
|
end
|
27
39
|
|
28
|
-
# Joins an `Either` through `Right`.
|
29
|
-
#
|
30
40
|
# @return [self]
|
31
|
-
#
|
32
41
|
def join_right
|
33
42
|
self
|
34
43
|
end
|
35
44
|
|
36
|
-
# Joins an `Either` through `Left`.
|
37
|
-
#
|
38
|
-
# This method requires that the left side of this `Either` is itself an
|
39
|
-
# Either type.
|
40
|
-
#
|
41
|
-
# This method, and `join_right`, are analogous to `Option#flatten`
|
42
|
-
#
|
43
45
|
# @return [Either]
|
44
|
-
# @raise [TypeError]
|
45
|
-
#
|
46
|
+
# @raise [TypeError]
|
46
47
|
def join_left
|
47
48
|
value.tap do |v|
|
48
49
|
Utils.assert_type!(v, Either)
|
data/lib/fear/none.rb
CHANGED
@@ -4,18 +4,27 @@ module Fear
|
|
4
4
|
include Dry::Equalizer()
|
5
5
|
include RightBiased::Left
|
6
6
|
|
7
|
-
#
|
8
|
-
|
7
|
+
# @raise [NoSuchElementError]
|
8
|
+
def get
|
9
|
+
fail NoSuchElementError
|
10
|
+
end
|
11
|
+
|
12
|
+
# @return [nil]
|
13
|
+
def or_nil
|
14
|
+
nil
|
15
|
+
end
|
16
|
+
|
17
|
+
# @return [true]
|
18
|
+
def empty?
|
19
|
+
true
|
20
|
+
end
|
21
|
+
|
9
22
|
# @return [None]
|
10
|
-
#
|
11
23
|
def select(*)
|
12
24
|
self
|
13
25
|
end
|
14
26
|
|
15
|
-
# Ignores the given block and return self.
|
16
|
-
#
|
17
27
|
# @return [None]
|
18
|
-
#
|
19
28
|
def reject(*)
|
20
29
|
self
|
21
30
|
end
|