monad-oxide 0.13.0 → 0.15.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/lib/monad-oxide.rb +16 -0
- data/lib/none.rb +139 -0
- data/lib/option.rb +196 -0
- data/lib/result.rb +22 -0
- data/lib/some.rb +140 -0
- data/lib/version.rb +1 -1
- metadata +5 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 5ef9afae9321a36b11f966859ba1e031288d0c532f758e4f9b7063234ab8fe2a
|
|
4
|
+
data.tar.gz: 9c1e4528650956209644f9095db174b510a4277e79c96d11f137ef1bb1ed708c
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 5270dd501e132f3396184508e05a1dc41e8ff119689a5a44a4b6c27bfcc4b23d5db18d53f8b5cdd68dc1915debe134ac27c8516fe143d165ba023414dbbc3d6f
|
|
7
|
+
data.tar.gz: 7badd118397b1bddc5a5c65b2e23f2c87e57d3c1ac10f774ee6863f3116aed9923f21d43693dbb1e4402128cd5c32e1640a7a8071c2083d29cfcdf977116ac9f
|
data/lib/monad-oxide.rb
CHANGED
|
@@ -4,6 +4,9 @@ require_relative './ok'
|
|
|
4
4
|
require_relative './either'
|
|
5
5
|
require_relative './left'
|
|
6
6
|
require_relative './right'
|
|
7
|
+
require_relative './option'
|
|
8
|
+
require_relative './some'
|
|
9
|
+
require_relative './none'
|
|
7
10
|
require_relative './array'
|
|
8
11
|
require_relative './version'
|
|
9
12
|
|
|
@@ -11,6 +14,7 @@ require_relative './version'
|
|
|
11
14
|
# The top level module for the monad-oxide library. Of interest, @see `Result',
|
|
12
15
|
# @see `Err', and @see `Ok'.
|
|
13
16
|
module MonadOxide
|
|
17
|
+
|
|
14
18
|
module_function
|
|
15
19
|
|
|
16
20
|
##
|
|
@@ -25,6 +29,10 @@ module MonadOxide
|
|
|
25
29
|
MonadOxide::Left.new(data)
|
|
26
30
|
end
|
|
27
31
|
|
|
32
|
+
def none()
|
|
33
|
+
MonadOxide::None.new()
|
|
34
|
+
end
|
|
35
|
+
|
|
28
36
|
##
|
|
29
37
|
# Create an `Ok' as a conveniece method.
|
|
30
38
|
# @param data [Object] The inner data for this `Ok'.
|
|
@@ -33,8 +41,16 @@ module MonadOxide
|
|
|
33
41
|
MonadOxide::Ok.new(data)
|
|
34
42
|
end
|
|
35
43
|
|
|
44
|
+
def option(data)
|
|
45
|
+
data.nil?() ? none() : some(data)
|
|
46
|
+
end
|
|
47
|
+
|
|
36
48
|
def right(data)
|
|
37
49
|
MonadOxide::Right.new(data)
|
|
38
50
|
end
|
|
39
51
|
|
|
52
|
+
def some(data)
|
|
53
|
+
MonadOxide::Some.new(data)
|
|
54
|
+
end
|
|
55
|
+
|
|
40
56
|
end
|
data/lib/none.rb
ADDED
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative './option'
|
|
4
|
+
|
|
5
|
+
module MonadOxide
|
|
6
|
+
|
|
7
|
+
##
|
|
8
|
+
# `None' represents the absence of a value in an `Option'.
|
|
9
|
+
#
|
|
10
|
+
# Any methods in Option that would process a present value (Some) will fall
|
|
11
|
+
# through with None instances.
|
|
12
|
+
class None < Option
|
|
13
|
+
|
|
14
|
+
##
|
|
15
|
+
# Create a None.
|
|
16
|
+
def initialize()
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
##
|
|
20
|
+
# Falls through. @see Option#and_then for how this is handled in either
|
|
21
|
+
# Option case, and @see Some#and_then for how this is handled in the Some
|
|
22
|
+
# case.
|
|
23
|
+
# @param f [Proc] Optional Proc - ignored.
|
|
24
|
+
# @yield An ignored block.
|
|
25
|
+
# @return [None] This None.
|
|
26
|
+
def and_then(f=nil, &block)
|
|
27
|
+
self
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
##
|
|
31
|
+
# Falls through. @see Option#inspect_some for how this is handled in
|
|
32
|
+
# either Option case, and @see Some#inspect_some for how this is handled
|
|
33
|
+
# in the Some case.
|
|
34
|
+
# @param f [Proc] Optional Proc - ignored.
|
|
35
|
+
# @yield An ignored block.
|
|
36
|
+
# @return [None] This None.
|
|
37
|
+
def inspect_some(f=nil, &block)
|
|
38
|
+
self
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
##
|
|
42
|
+
# Applies `f' or the block and returns the same `None'. No changes are
|
|
43
|
+
# applied. This is ideal for logging.
|
|
44
|
+
# @param f [Proc<B>] The function to call. Could be a block instead. Takes
|
|
45
|
+
# nothing, the return is ignored.
|
|
46
|
+
# @yield Will yield a block that takes nothing, the return is ignored.
|
|
47
|
+
# Same as `f' parameter.
|
|
48
|
+
# @return [Option] returns self.
|
|
49
|
+
def inspect_none(f=nil, &block)
|
|
50
|
+
(f || block).call()
|
|
51
|
+
self
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
##
|
|
55
|
+
# Falls through. @see Option#map for how this is handled in either
|
|
56
|
+
# Option case, and @see Some#map for how this is handled in the Some
|
|
57
|
+
# case.
|
|
58
|
+
# @param f [Proc] Optional Proc - ignored.
|
|
59
|
+
# @yield An ignored block.
|
|
60
|
+
# @return [None] This None.
|
|
61
|
+
def map(f=nil, &block)
|
|
62
|
+
self
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
##
|
|
66
|
+
# Applies `f' or the block and returns a new `Option' with the returned
|
|
67
|
+
# value.
|
|
68
|
+
# @param f [Proc<B>] The function to call. Could be a block instead. Takes
|
|
69
|
+
# nothing and returns a B.
|
|
70
|
+
# @yield Will yield a block that takes nothing and returns a B. Same as
|
|
71
|
+
# `f' parameter.
|
|
72
|
+
# @return [Option<B>] A new `Option<B>' whose `B' is the return of `f' or
|
|
73
|
+
# the block.
|
|
74
|
+
def map_none(f=nil, &block)
|
|
75
|
+
Some.new((f || block).call())
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
##
|
|
79
|
+
# Identifies that this is a `None'.
|
|
80
|
+
# For counterparts:
|
|
81
|
+
# @see MonadOxide::Some#some?
|
|
82
|
+
# @see MonadOxide::Some#none?
|
|
83
|
+
# @see MonadOxide::None#some?
|
|
84
|
+
# @return [Boolean] `true` because this is a `None'.
|
|
85
|
+
def none?()
|
|
86
|
+
true
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
##
|
|
90
|
+
# Invokes `f' or the block and returns the Option returned from that. The
|
|
91
|
+
# return type is enforced.
|
|
92
|
+
# @param f [Proc<Option<B>>] The function to call. Could be a block
|
|
93
|
+
# instead. Takes nothing and must return a [Option<B>].
|
|
94
|
+
# @yield Will yield a block that takes nothing and returns a Option<B>.
|
|
95
|
+
# Same as `f' parameter.
|
|
96
|
+
# @return [Some<B> | None] A new Option from `f' or the block. If `f'
|
|
97
|
+
# returns a non-Option, this will raise
|
|
98
|
+
# `OptionReturnExpectedError'.
|
|
99
|
+
def or_else(f=nil, &block)
|
|
100
|
+
option = (f || block).call()
|
|
101
|
+
if !option.kind_of?(Option)
|
|
102
|
+
raise OptionReturnExpectedError.new(option)
|
|
103
|
+
else
|
|
104
|
+
option
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
##
|
|
109
|
+
# Identifies that this is not a `Some'.
|
|
110
|
+
# For counterparts:
|
|
111
|
+
# @see MonadOxide::Some#some?
|
|
112
|
+
# @see MonadOxide::Some#none?
|
|
113
|
+
# @see MonadOxide::None#none?
|
|
114
|
+
# @return [Boolean] `false` because this is not a `Some'.
|
|
115
|
+
def some?()
|
|
116
|
+
false
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
##
|
|
120
|
+
# Dangerously try to access the `Option' data. If this is a `None', an
|
|
121
|
+
# exception will be raised. It is recommended to use this for tests only.
|
|
122
|
+
# @return [A] The inner data of this `Option'.
|
|
123
|
+
def unwrap()
|
|
124
|
+
raise UnwrapError.new(
|
|
125
|
+
"#{self.class} could not be unwrapped as a Some.",
|
|
126
|
+
)
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
##
|
|
130
|
+
# Dangerously access the `None' data. If this is a `Some', an exception
|
|
131
|
+
# will be raised. It is recommended to use this for tests only.
|
|
132
|
+
# @return [nil] Returns nil for `None'.
|
|
133
|
+
def unwrap_none()
|
|
134
|
+
nil
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
end
|
data/lib/option.rb
ADDED
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
################################################################################
|
|
3
|
+
# An Option represents a value that may or may not be present. Some languages
|
|
4
|
+
# also calls this a Maybe. This is represented by two subclasses: Some and
|
|
5
|
+
# None. Some represents a present value, and None means no value is present.
|
|
6
|
+
# It is advantageous to use this over `nil` because, unlike `nil`, you can
|
|
7
|
+
# compose over `Option`.
|
|
8
|
+
################################################################################
|
|
9
|
+
|
|
10
|
+
module MonadOxide
|
|
11
|
+
|
|
12
|
+
##
|
|
13
|
+
# Thie Exception signals an area under construction, or somehow the consumer
|
|
14
|
+
# wound up with a base class instance and not one of its
|
|
15
|
+
# subclasses. Implementors of new methods on subclasses should
|
|
16
|
+
# create methods on the base class as well which immediately raise this
|
|
17
|
+
# `Exception'.
|
|
18
|
+
class OptionMethodNotImplementedError < MonadOxideError; end
|
|
19
|
+
|
|
20
|
+
##
|
|
21
|
+
# This `Exception' is produced when a method that expects the function or
|
|
22
|
+
# block to provide a `Result' but was given something else. Generally this
|
|
23
|
+
# Exception is not raised, but instead converts the Result into a an Err.
|
|
24
|
+
# Example methods with this behavior are Result#and_then and Result#or_else.
|
|
25
|
+
class OptionReturnExpectedError < MonadOxideError
|
|
26
|
+
##
|
|
27
|
+
# The transformation expected a `Result' but got something else.
|
|
28
|
+
# @param data [Object] Whatever we got that wasn't a `Result'.
|
|
29
|
+
def initialize(data)
|
|
30
|
+
super("A Result was expected but got #{data.inspect}.")
|
|
31
|
+
data = @data
|
|
32
|
+
end
|
|
33
|
+
attr_reader(:data)
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
##
|
|
37
|
+
# An Option is a chainable series of sequential transformations. The Option
|
|
38
|
+
# structure contains a `Some<A> | None`. This is the central location
|
|
39
|
+
# for documentation between both `Some' and `None'. It is best to think of
|
|
40
|
+
# any given `Some' or `None' as an `Option' instead. All methods on `Some'
|
|
41
|
+
# are present on `None' and vice versa. This way we can interchange one for
|
|
42
|
+
# the other during virtually any call.
|
|
43
|
+
#
|
|
44
|
+
# This is a base-class only, and you should never see instances of these in
|
|
45
|
+
# the wild.
|
|
46
|
+
class Option
|
|
47
|
+
|
|
48
|
+
def initialize(data)
|
|
49
|
+
raise NoMethodError.new('Do not use Option directly. See Some and None.')
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
##
|
|
53
|
+
# Determine if this is a MonadOxide::Some.
|
|
54
|
+
# @return [Boolean] `true` if this is a MonadOxide::Some, `false`
|
|
55
|
+
# otherwise.
|
|
56
|
+
def some?()
|
|
57
|
+
false
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
##
|
|
61
|
+
# Determine if this is a MonadOxide::None.
|
|
62
|
+
# @return [Boolean] `true` if this is a MonadOxide::None, `false`
|
|
63
|
+
# otherwise.
|
|
64
|
+
def none?()
|
|
65
|
+
false
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
##
|
|
69
|
+
# In the case of `Some', applies `f' or the block over the data and
|
|
70
|
+
# returns a new `Some' with the returned value. For `None', this method
|
|
71
|
+
# falls through.
|
|
72
|
+
# @param f [Proc<A, B>] The function to call. Could be a block instead.
|
|
73
|
+
# Takes an [A=Object] and returns a B.
|
|
74
|
+
# @yield Will yield a block that takes an A and returns a B. Same as `f'
|
|
75
|
+
# parameter.
|
|
76
|
+
# @return [Option<B>] A new `Option<B>' whose `B' is the return of `f' or
|
|
77
|
+
# the block for `Some'. For `None', returns self.
|
|
78
|
+
def map(f=nil, &block)
|
|
79
|
+
raise OptionMethodNotImplementedError.new()
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
##
|
|
83
|
+
# In the case of `None', applies `f' or the block and returns a new
|
|
84
|
+
# `Option' with the returned value. For `Some', this method falls through.
|
|
85
|
+
# @param f [Proc<B>] The function to call. Could be a block instead. Takes
|
|
86
|
+
# nothing and returns a B.
|
|
87
|
+
# @yield Will yield a block that takes nothing and returns a B. Same as
|
|
88
|
+
# `f' parameter.
|
|
89
|
+
# @return [Option<B>] A new `Option<B>' whose `B' is the return of `f' or
|
|
90
|
+
# the block for `None'. For `Some', returns self.
|
|
91
|
+
def map_none(f=nil, &block)
|
|
92
|
+
raise OptionMethodNotImplementedError.new()
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
##
|
|
96
|
+
# In the case of `Some', applies `f' or the block over the data and
|
|
97
|
+
# returns the same `Some'. No changes are applied. This is ideal for
|
|
98
|
+
# logging. For `None', this method falls through.
|
|
99
|
+
# @param f [Proc<A, B>] The function to call. Could be a block instead.
|
|
100
|
+
# Takes an [A] the return is ignored.
|
|
101
|
+
# @yield Will yield a block that takes an A the return is ignored. Same as
|
|
102
|
+
# `f' parameter.
|
|
103
|
+
# @return [Option<A>] returns self.
|
|
104
|
+
def inspect_some(f=nil, &block)
|
|
105
|
+
raise OptionMethodNotImplementedError.new()
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
##
|
|
109
|
+
# In the case of `None', applies `f' or the block and returns the same
|
|
110
|
+
# `None'. No changes are applied. This is ideal for logging. For `Some',
|
|
111
|
+
# this method falls through.
|
|
112
|
+
# @param f [Proc<B>] The function to call. Could be a block instead. Takes
|
|
113
|
+
# nothing, the return is ignored.
|
|
114
|
+
# @yield Will yield a block that takes nothing, the return is ignored.
|
|
115
|
+
# Same as `f' parameter.
|
|
116
|
+
# @return [Option] returns self.
|
|
117
|
+
def inspect_none(f=nil, &block)
|
|
118
|
+
raise OptionMethodNotImplementedError.new()
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
##
|
|
122
|
+
# For `Some', invokes `f' or the block with the data and returns the
|
|
123
|
+
# Option returned from that.
|
|
124
|
+
#
|
|
125
|
+
# For `None', returns itself and the function/block are ignored.
|
|
126
|
+
#
|
|
127
|
+
# This method is used for control flow based on `Option' values.
|
|
128
|
+
#
|
|
129
|
+
# `and_then' is desirable for chaining together other Option based
|
|
130
|
+
# operations, or doing transformations where flipping from a `Some' to a
|
|
131
|
+
# `None' is desired. In cases where there is little/no risk of a `None'
|
|
132
|
+
# state, @see Option#map.
|
|
133
|
+
#
|
|
134
|
+
# The `None' equivalent operation is @see Option#or_else.
|
|
135
|
+
#
|
|
136
|
+
# The return type is enforced.
|
|
137
|
+
#
|
|
138
|
+
# @param f [Proc<A, Option<B>>] The function to call. Could be a block
|
|
139
|
+
# instead. Takes an [A=Object] and must return a [Option<B>].
|
|
140
|
+
# @yield Will yield a block that takes an A and returns a Option<B>. Same
|
|
141
|
+
# as `f' parameter.
|
|
142
|
+
# @return [Some<B> | None] A new Option from `f' or the block. If `f'
|
|
143
|
+
# returns a non-Option, this will raise
|
|
144
|
+
# `OptionReturnExpectedError'.
|
|
145
|
+
def and_then(f=nil, &block)
|
|
146
|
+
raise OptionMethodNotImplementedError.new()
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
##
|
|
150
|
+
# For `None', invokes `f' or the block and returns the Option returned
|
|
151
|
+
# from that.
|
|
152
|
+
#
|
|
153
|
+
# For `Some', returns itself and the function/block are ignored.
|
|
154
|
+
#
|
|
155
|
+
# This method is used for control flow based on `Option' values.
|
|
156
|
+
#
|
|
157
|
+
# `or_else' is desirable for chaining together other Option based
|
|
158
|
+
# operations, or doing transformations where flipping from a `None' to a
|
|
159
|
+
# `Some' is desired.
|
|
160
|
+
#
|
|
161
|
+
# The `Some' equivalent operation is @see Option#and_then.
|
|
162
|
+
#
|
|
163
|
+
# The return type is enforced.
|
|
164
|
+
#
|
|
165
|
+
# @param f [Proc<Option<B>>] The function to call. Could be a block
|
|
166
|
+
# instead. Takes nothing and must return a [Option<B>].
|
|
167
|
+
# @yield Will yield a block that takes nothing and returns a Option<B>.
|
|
168
|
+
# Same as `f' parameter.
|
|
169
|
+
# @return [Some<B> | None] A new Option from `f' or the block. If `f'
|
|
170
|
+
# returns a non-Option, this will raise
|
|
171
|
+
# `OptionReturnExpectedError'.
|
|
172
|
+
def or_else(f=nil, &block)
|
|
173
|
+
raise OptionMethodNotImplementedError.new()
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
##
|
|
177
|
+
# Dangerously access the `Option' data. If this is a `None', an exception
|
|
178
|
+
# will be raised. It is recommended to use this for tests only.
|
|
179
|
+
# @raise [UnwrapError] if called on a `None'.
|
|
180
|
+
# @return [A] - The inner data of this `Some'.
|
|
181
|
+
def unwrap()
|
|
182
|
+
raise OptionMethodNotImplementedError.new()
|
|
183
|
+
end
|
|
184
|
+
|
|
185
|
+
##
|
|
186
|
+
# Dangerously access the `Option' data. If this is a `Some', an exception
|
|
187
|
+
# will be raised. It is recommended to use this for tests only.
|
|
188
|
+
# @raise [UnwrapError] if called on a `Some'.
|
|
189
|
+
# @return [nil] - Returns nil for `None'.
|
|
190
|
+
def unwrap_none()
|
|
191
|
+
raise OptionMethodNotImplementedError.new()
|
|
192
|
+
end
|
|
193
|
+
|
|
194
|
+
end
|
|
195
|
+
|
|
196
|
+
end
|
data/lib/result.rb
CHANGED
|
@@ -58,6 +58,28 @@ module MonadOxide
|
|
|
58
58
|
# protected :new
|
|
59
59
|
# end
|
|
60
60
|
|
|
61
|
+
class << self
|
|
62
|
+
|
|
63
|
+
##
|
|
64
|
+
# Convenience for executing arbitrary code and coercing it to a Result.
|
|
65
|
+
# Any exceptions raised coerce it into an Err, and the return value is the
|
|
66
|
+
# value for the Ok.
|
|
67
|
+
# @param f [Proc<Result<A>>] The function to call. Could be a block
|
|
68
|
+
# instead. Takes no arguments and could return any [Object].
|
|
69
|
+
# @yield Will yield a block that takes no arguments A and returns a
|
|
70
|
+
# [Object]. Same as `f' parameter.
|
|
71
|
+
# @return [MonadOxide::Result<A, E>] An Ok if there are no exceptions
|
|
72
|
+
# raised, and an Err with the exception if any exception is raised.
|
|
73
|
+
def try(f=nil, &block)
|
|
74
|
+
begin
|
|
75
|
+
MonadOxide.ok((f || block).call())
|
|
76
|
+
rescue => e
|
|
77
|
+
MonadOxide.err(e)
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
end
|
|
82
|
+
|
|
61
83
|
def initialize(data)
|
|
62
84
|
raise NoMethodError.new('Do not use Result directly. See Ok and Err.')
|
|
63
85
|
end
|
data/lib/some.rb
ADDED
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative './option'
|
|
4
|
+
require_relative './error'
|
|
5
|
+
|
|
6
|
+
module MonadOxide
|
|
7
|
+
|
|
8
|
+
##
|
|
9
|
+
# `Some' represents a present value in an `Option'. For most operations,
|
|
10
|
+
# `Some' will perform some operation.
|
|
11
|
+
class Some < Option
|
|
12
|
+
|
|
13
|
+
##
|
|
14
|
+
# Constructs a `Some' with the data provided.
|
|
15
|
+
# @param data [Object] The inner data this Option encapsulates.
|
|
16
|
+
def initialize(data)
|
|
17
|
+
@data = data
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
##
|
|
21
|
+
# Invokes `f' or the block with the data and returns the Option returned
|
|
22
|
+
# from that. The return type is enforced.
|
|
23
|
+
# @param f [Proc<A, Option<B>>] The function to call. Could be a block
|
|
24
|
+
# instead. Takes an [A=Object] and must return a [Option<B>].
|
|
25
|
+
# @yield Will yield a block that takes an A and returns a Option<B>. Same
|
|
26
|
+
# as `f' parameter.
|
|
27
|
+
# @return [Some<B> | None] A new Option from `f' or the block. If `f'
|
|
28
|
+
# returns a non-Option, this will raise
|
|
29
|
+
# `OptionReturnExpectedError'.
|
|
30
|
+
def and_then(f=nil, &block)
|
|
31
|
+
option = (f || block).call(@data)
|
|
32
|
+
if !option.kind_of?(Option)
|
|
33
|
+
raise OptionReturnExpectedError.new(option)
|
|
34
|
+
else
|
|
35
|
+
option
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
##
|
|
40
|
+
# Applies `f' or the block over the data and returns the same `Some'. No
|
|
41
|
+
# changes are applied. This is ideal for logging.
|
|
42
|
+
# @param f [Proc<A, B>] The function to call. Could be a block instead.
|
|
43
|
+
# Takes an [A] the return is ignored.
|
|
44
|
+
# @yield Will yield a block that takes an A the return is ignored. Same as
|
|
45
|
+
# `f' parameter.
|
|
46
|
+
# @return [Option<A>] returns self.
|
|
47
|
+
def inspect_some(f=nil, &block)
|
|
48
|
+
(f || block).call(@data)
|
|
49
|
+
self
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
##
|
|
53
|
+
# Falls through. @see Option#inspect_none for how this is handled in
|
|
54
|
+
# either Option case, and @see None#inspect_none for how this is handled
|
|
55
|
+
# in the None case.
|
|
56
|
+
# @param f [Proc] Optional Proc - ignored.
|
|
57
|
+
# @yield An ignored block.
|
|
58
|
+
# @return [Some] This Some.
|
|
59
|
+
def inspect_none(f=nil, &block)
|
|
60
|
+
self
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
##
|
|
64
|
+
# Applies `f' or the block over the data and returns a new `Some' with
|
|
65
|
+
# the returned value.
|
|
66
|
+
# @param f [Proc<A, B>] The function to call. Could be a block instead.
|
|
67
|
+
# Takes an [A=Object] and returns a B.
|
|
68
|
+
# @yield Will yield a block that takes an A and returns a B. Same as `f'
|
|
69
|
+
# parameter.
|
|
70
|
+
# @return [Option<B>] A new `Some<B>' whose `B' is the return of `f' or
|
|
71
|
+
# the block.
|
|
72
|
+
def map(f=nil, &block)
|
|
73
|
+
self.class.new((f || block).call(@data))
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
##
|
|
77
|
+
# This is a no-op for Some. @see None#map_none.
|
|
78
|
+
# @param f [Proc<A, B>] A dummy function. Not used.
|
|
79
|
+
# @yield A dummy block. Not used.
|
|
80
|
+
# @return [Option<A>] This `Some'.
|
|
81
|
+
def map_none(f=nil, &block)
|
|
82
|
+
self
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
##
|
|
86
|
+
# Identifies that this is not a `None'.
|
|
87
|
+
# For counterparts:
|
|
88
|
+
# @see MonadOxide::Some#some?
|
|
89
|
+
# @see MonadOxide::None#some?
|
|
90
|
+
# @see MonadOxide::None#none?
|
|
91
|
+
# @return [Boolean] `false` because this is not a `None'.
|
|
92
|
+
def none?()
|
|
93
|
+
false
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
##
|
|
97
|
+
# The None equivalent to Some#and_then. This is a no-op for Some. @see
|
|
98
|
+
# None#or_else.
|
|
99
|
+
# @param f [Proc<A, B>] A dummy function. Not used.
|
|
100
|
+
# @yield A dummy block. Not used.
|
|
101
|
+
# @return [Option<A>] This `Some'.
|
|
102
|
+
def or_else(f=nil, &block)
|
|
103
|
+
self
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
##
|
|
107
|
+
# Identifies that this is a `Some'.
|
|
108
|
+
# For counterparts:
|
|
109
|
+
# @see MonadOxide::Some#none?
|
|
110
|
+
# @see MonadOxide::None#some?
|
|
111
|
+
# @see MonadOxide::None#none?
|
|
112
|
+
# @return [Boolean] `true` because this is a `Some'.
|
|
113
|
+
def some?()
|
|
114
|
+
true
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
##
|
|
118
|
+
# Dangerously access the `Some' data. If this is a `None', an exception
|
|
119
|
+
# will be raised. It is recommended to use this for tests only.
|
|
120
|
+
# @return [A] The inner data of this `Some'.
|
|
121
|
+
def unwrap()
|
|
122
|
+
@data
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
##
|
|
126
|
+
# Dangerously access the `None' data. If this is a `Some', an exception
|
|
127
|
+
# will be raised. It is recommended to use this for tests only.
|
|
128
|
+
# @return [nil] Returns nil for `None'.
|
|
129
|
+
def unwrap_none()
|
|
130
|
+
raise UnwrapError.new(
|
|
131
|
+
<<~EOE
|
|
132
|
+
#{self.class} with #{@data.inspect()} could not be unwrapped as a
|
|
133
|
+
None.
|
|
134
|
+
EOE
|
|
135
|
+
)
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
end
|
data/lib/version.rb
CHANGED
|
@@ -3,5 +3,5 @@ module MonadOxide
|
|
|
3
3
|
# This version is locked to 0.x.0 because semver is a lie and this project
|
|
4
4
|
# uses CICD to push new versions. Any commits that appear on main will result
|
|
5
5
|
# in a new version of the gem created and published.
|
|
6
|
-
VERSION='0.
|
|
6
|
+
VERSION='0.15.0'
|
|
7
7
|
end
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: monad-oxide
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.15.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Logan Barnett
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2025-
|
|
11
|
+
date: 2025-11-07 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: org-ruby
|
|
@@ -81,9 +81,12 @@ files:
|
|
|
81
81
|
- lib/error.rb
|
|
82
82
|
- lib/left.rb
|
|
83
83
|
- lib/monad-oxide.rb
|
|
84
|
+
- lib/none.rb
|
|
84
85
|
- lib/ok.rb
|
|
86
|
+
- lib/option.rb
|
|
85
87
|
- lib/result.rb
|
|
86
88
|
- lib/right.rb
|
|
89
|
+
- lib/some.rb
|
|
87
90
|
- lib/version.rb
|
|
88
91
|
homepage:
|
|
89
92
|
licenses:
|