dry-monads 0.4.0 → 1.0.0.beta1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.travis.yml +7 -4
- data/CHANGELOG.md +141 -1
- data/CONTRIBUTING.md +1 -1
- data/LICENSE +1 -1
- data/README.md +2 -2
- data/dry-monads.gemspec +2 -1
- data/lib/dry/monads.rb +22 -1
- data/lib/dry/monads/curry.rb +19 -0
- data/lib/dry/monads/do.rb +119 -0
- data/lib/dry/monads/either.rb +63 -0
- data/lib/dry/monads/errors.rb +3 -1
- data/lib/dry/monads/lazy.rb +78 -0
- data/lib/dry/monads/list.rb +109 -12
- data/lib/dry/monads/maybe.rb +50 -24
- data/lib/dry/monads/result.rb +93 -49
- data/lib/dry/monads/result/fixed.rb +2 -2
- data/lib/dry/monads/right_biased.rb +18 -27
- data/lib/dry/monads/task.rb +309 -0
- data/lib/dry/monads/transformer.rb +1 -0
- data/lib/dry/monads/traverse.rb +20 -0
- data/lib/dry/monads/try.rb +111 -39
- data/lib/dry/monads/validated.rb +283 -0
- data/lib/dry/monads/version.rb +2 -1
- data/lib/json/add/dry/monads/maybe.rb +1 -1
- metadata +29 -9
data/lib/dry/monads/result.rb
CHANGED
@@ -13,15 +13,25 @@ module Dry
|
|
13
13
|
class Result
|
14
14
|
include Transformer
|
15
15
|
|
16
|
-
|
16
|
+
# @return [Object] Successful result
|
17
|
+
attr_reader :success
|
18
|
+
|
19
|
+
# @return [Object] Error
|
20
|
+
attr_reader :failure
|
17
21
|
|
18
22
|
class << self
|
19
|
-
# Wraps the given value with Success
|
23
|
+
# Wraps the given value with Success.
|
20
24
|
#
|
21
|
-
# @
|
22
|
-
#
|
23
|
-
|
24
|
-
|
25
|
+
# @overload pure(value)
|
26
|
+
# @param value [Object]
|
27
|
+
# @return [Result::Success]
|
28
|
+
#
|
29
|
+
# @overload pure(&block)
|
30
|
+
# @param block [Proc] a block to be wrapped with Success
|
31
|
+
# @return [Result::Success]
|
32
|
+
#
|
33
|
+
def pure(value = Undefined, &block)
|
34
|
+
Success.new(Undefined.default(value, block))
|
25
35
|
end
|
26
36
|
end
|
27
37
|
|
@@ -31,7 +41,13 @@ module Dry
|
|
31
41
|
def to_result
|
32
42
|
self
|
33
43
|
end
|
34
|
-
|
44
|
+
|
45
|
+
# Returns self.
|
46
|
+
#
|
47
|
+
# @return [Result::Success, Result::Failure]
|
48
|
+
def to_monad
|
49
|
+
self
|
50
|
+
end
|
35
51
|
|
36
52
|
# Returns the Result monad.
|
37
53
|
# This is how we're doing polymorphism in Ruby 😕
|
@@ -66,13 +82,11 @@ module Dry
|
|
66
82
|
def failure?
|
67
83
|
false
|
68
84
|
end
|
69
|
-
alias_method :left?, :failure?
|
70
85
|
|
71
86
|
# Returns true
|
72
87
|
def success?
|
73
88
|
true
|
74
89
|
end
|
75
|
-
alias_method :right?, :success?
|
76
90
|
|
77
91
|
# Does the same thing as #bind except it also wraps the value
|
78
92
|
# in an instance of Result::Success monad. This allows for easier
|
@@ -99,11 +113,18 @@ module Dry
|
|
99
113
|
Dry::Monads::Maybe(@value)
|
100
114
|
end
|
101
115
|
|
102
|
-
#
|
116
|
+
# Transforms to a Failure instance
|
103
117
|
#
|
104
118
|
# @return [Result::Failure]
|
105
119
|
def flip
|
106
|
-
Failure.new(@value)
|
120
|
+
Failure.new(@value, RightBiased::Left.trace_caller)
|
121
|
+
end
|
122
|
+
|
123
|
+
# Transforms to Validated
|
124
|
+
#
|
125
|
+
# @return [Validated::Valid]
|
126
|
+
def to_validated
|
127
|
+
Validated::Valid.new(value!)
|
107
128
|
end
|
108
129
|
end
|
109
130
|
|
@@ -114,15 +135,22 @@ module Dry
|
|
114
135
|
include RightBiased::Left
|
115
136
|
include Dry::Equalizer(:failure)
|
116
137
|
|
117
|
-
#
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
138
|
+
# Line where the value was constructed
|
139
|
+
#
|
140
|
+
# @return [String]
|
141
|
+
# @api public
|
142
|
+
attr_reader :trace
|
122
143
|
|
123
|
-
# @param value [Object]
|
124
|
-
|
144
|
+
# @param value [Object] failure value
|
145
|
+
# @param trace [String] caller line
|
146
|
+
def initialize(value, trace = RightBiased::Left.trace_caller)
|
125
147
|
@value = value
|
148
|
+
@trace = trace
|
149
|
+
end
|
150
|
+
|
151
|
+
# @private
|
152
|
+
def failure
|
153
|
+
@value
|
126
154
|
end
|
127
155
|
|
128
156
|
# Apply the first function to value.
|
@@ -136,13 +164,11 @@ module Dry
|
|
136
164
|
def failure?
|
137
165
|
true
|
138
166
|
end
|
139
|
-
alias_method :left?, :failure?
|
140
167
|
|
141
168
|
# Returns false
|
142
169
|
def success?
|
143
170
|
false
|
144
171
|
end
|
145
|
-
alias_method :right?, :success?
|
146
172
|
|
147
173
|
# If a block is given passes internal value to it and returns the result,
|
148
174
|
# otherwise simply returns the first argument.
|
@@ -182,7 +208,7 @@ module Dry
|
|
182
208
|
|
183
209
|
# @return [Maybe::None]
|
184
210
|
def to_maybe
|
185
|
-
Maybe::None.
|
211
|
+
Maybe::None.new(trace)
|
186
212
|
end
|
187
213
|
|
188
214
|
# Transform to a Success instance
|
@@ -192,7 +218,7 @@ module Dry
|
|
192
218
|
Success.new(@value)
|
193
219
|
end
|
194
220
|
|
195
|
-
# @see
|
221
|
+
# @see RightBiased::Left#value_or
|
196
222
|
def value_or(val = nil)
|
197
223
|
if block_given?
|
198
224
|
yield(@value)
|
@@ -206,45 +232,63 @@ module Dry
|
|
206
232
|
def ===(other)
|
207
233
|
Failure === other && failure === other.failure
|
208
234
|
end
|
235
|
+
|
236
|
+
# Transforms to Validated
|
237
|
+
#
|
238
|
+
# @return [Validated::Valid]
|
239
|
+
def to_validated
|
240
|
+
Validated::Invalid.new(failure, trace)
|
241
|
+
end
|
209
242
|
end
|
210
243
|
|
211
244
|
# A module that can be included for easier access to Result monads.
|
245
|
+
#
|
246
|
+
# @api public
|
212
247
|
module Mixin
|
213
|
-
|
214
|
-
|
248
|
+
# @see Result::Success
|
249
|
+
Success = Result::Success
|
250
|
+
# @see Result::Failure
|
251
|
+
Failure = Result::Failure
|
215
252
|
|
253
|
+
# Value constructors
|
254
|
+
#
|
216
255
|
module Constructors
|
217
|
-
|
218
|
-
#
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
256
|
+
|
257
|
+
# Success constructor
|
258
|
+
#
|
259
|
+
# @overload Success(value)
|
260
|
+
# @param value [Object]
|
261
|
+
# @return [Result::Success]
|
262
|
+
#
|
263
|
+
# @overload Success(&block)
|
264
|
+
# @param block [Proc] a block to be wrapped with Success
|
265
|
+
# @return [Result::Success]
|
266
|
+
#
|
267
|
+
def Success(value = Undefined, &block)
|
268
|
+
v = Undefined.default(value, block)
|
269
|
+
raise ArgumentError, 'No value given' if !value.nil? && v.nil?
|
270
|
+
Success.new(v)
|
226
271
|
end
|
227
|
-
|
228
|
-
|
229
|
-
#
|
230
|
-
# @
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
272
|
+
|
273
|
+
# Failure constructor
|
274
|
+
#
|
275
|
+
# @overload Success(value)
|
276
|
+
# @param value [Object]
|
277
|
+
# @return [Result::Failure]
|
278
|
+
#
|
279
|
+
# @overload Success(&block)
|
280
|
+
# @param block [Proc] a block to be wrapped with Failure
|
281
|
+
# @return [Result::Failure]
|
282
|
+
#
|
283
|
+
def Failure(value = Undefined, &block)
|
284
|
+
v = Undefined.default(value, block)
|
285
|
+
raise ArgumentError, 'No value given' if !value.nil? && v.nil?
|
286
|
+
Failure.new(v, RightBiased::Left.trace_caller)
|
238
287
|
end
|
239
|
-
alias_method :Left, :Failure
|
240
288
|
end
|
241
289
|
|
242
290
|
include Constructors
|
243
291
|
end
|
244
292
|
end
|
245
|
-
|
246
|
-
Either = Result
|
247
|
-
Result::Right = Result::Success
|
248
|
-
Result::Left = Result::Failure
|
249
293
|
end
|
250
294
|
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
module Dry::Monads
|
2
2
|
class Result
|
3
3
|
# @see Monads#Result
|
4
|
-
# @
|
4
|
+
# @private
|
5
5
|
class Fixed < Module
|
6
6
|
def self.[](error, **options)
|
7
7
|
new(error, **options)
|
@@ -11,7 +11,7 @@ module Dry::Monads
|
|
11
11
|
@mod = Module.new do
|
12
12
|
define_method(:Failure) do |value|
|
13
13
|
if error === value
|
14
|
-
Failure.new(value)
|
14
|
+
Failure.new(value, RightBiased::Left.trace_caller)
|
15
15
|
else
|
16
16
|
raise InvalidFailureTypeError.new(value)
|
17
17
|
end
|
@@ -1,17 +1,18 @@
|
|
1
1
|
require 'dry/core/constants'
|
2
|
-
require 'dry/core/deprecations'
|
3
2
|
|
3
|
+
require 'dry/monads/curry'
|
4
4
|
require 'dry/monads/errors'
|
5
5
|
|
6
6
|
module Dry
|
7
7
|
module Monads
|
8
|
+
# A common module for right-biased monads, such as Result/Either, Maybe, and Try.
|
8
9
|
module RightBiased
|
10
|
+
# Right part
|
11
|
+
#
|
9
12
|
# @api public
|
10
13
|
module Right
|
11
14
|
include Dry::Core::Constants
|
12
15
|
|
13
|
-
extend Dry::Core::Deprecations[:'dry-monads']
|
14
|
-
|
15
16
|
# Unwraps the underlying value
|
16
17
|
#
|
17
18
|
# @return [Object]
|
@@ -19,8 +20,6 @@ module Dry
|
|
19
20
|
@value
|
20
21
|
end
|
21
22
|
|
22
|
-
deprecate :value, :value!
|
23
|
-
|
24
23
|
# Calls the passed in Proc object with value stored in self
|
25
24
|
# and returns the result.
|
26
25
|
#
|
@@ -65,8 +64,8 @@ module Dry
|
|
65
64
|
bind(*args, &block).bind { self }
|
66
65
|
end
|
67
66
|
|
68
|
-
# Abstract method for lifting a block over the monad type
|
69
|
-
# Must be implemented for a right-biased monad
|
67
|
+
# Abstract method for lifting a block over the monad type.
|
68
|
+
# Must be implemented for a right-biased monad.
|
70
69
|
#
|
71
70
|
# @return [RightBiased::Right]
|
72
71
|
def fmap(*)
|
@@ -97,7 +96,7 @@ module Dry
|
|
97
96
|
end
|
98
97
|
|
99
98
|
# Applies the stored value to the given argument if the argument has type of Right,
|
100
|
-
# otherwise returns the argument
|
99
|
+
# otherwise returns the argument.
|
101
100
|
#
|
102
101
|
# @example happy path
|
103
102
|
# create_user = Dry::Monads::Right(CreateUser.new)
|
@@ -109,11 +108,12 @@ module Dry
|
|
109
108
|
# create_user.apply(name) # => Left(:name_missing)
|
110
109
|
#
|
111
110
|
# @return [RightBiased::Left,RightBiased::Right]
|
112
|
-
def apply(val)
|
111
|
+
def apply(val = Undefined)
|
113
112
|
unless @value.respond_to?(:call)
|
114
113
|
raise TypeError, "Cannot apply #{ val.inspect } to #{ @value.inspect }"
|
115
114
|
end
|
116
|
-
|
115
|
+
|
116
|
+
Undefined.default(val) { yield }.fmap { |unwrapped| curry.(unwrapped) }
|
117
117
|
end
|
118
118
|
|
119
119
|
# @param other [RightBiased]
|
@@ -131,28 +131,19 @@ module Dry
|
|
131
131
|
|
132
132
|
# @api private
|
133
133
|
def curry
|
134
|
-
@curried ||=
|
135
|
-
begin
|
136
|
-
func = @value.is_a?(Proc) ? @value : @value.method(:call)
|
137
|
-
seq_args = func.parameters.count { |type, _| type == :req }
|
138
|
-
seq_args += 1 if func.parameters.any? { |type, _| type == :keyreq }
|
139
|
-
|
140
|
-
if seq_args > 1
|
141
|
-
func.curry
|
142
|
-
else
|
143
|
-
func
|
144
|
-
end
|
145
|
-
end
|
134
|
+
@curried ||= Curry.(@value)
|
146
135
|
end
|
147
136
|
end
|
148
137
|
|
138
|
+
# Left/wrong/erroneous part
|
139
|
+
#
|
149
140
|
# @api public
|
150
141
|
module Left
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
142
|
+
# @private
|
143
|
+
# @return [String] Caller location
|
144
|
+
def self.trace_caller
|
145
|
+
caller_locations(2, 2)[0].to_s
|
146
|
+
end
|
156
147
|
|
157
148
|
# Raises an error on accessing internal value
|
158
149
|
def value!
|
@@ -0,0 +1,309 @@
|
|
1
|
+
require 'concurrent/promise'
|
2
|
+
|
3
|
+
require 'dry/monads/curry'
|
4
|
+
|
5
|
+
module Dry
|
6
|
+
module Monads
|
7
|
+
# The Task monad represents an async computation. The implementation
|
8
|
+
# is a rather thin wrapper of Concurrent::Promise from the concurrent-ruby.
|
9
|
+
# The API supports setting a custom executor from concurrent-ruby.
|
10
|
+
#
|
11
|
+
# @api public
|
12
|
+
class Task
|
13
|
+
# @api private
|
14
|
+
class Promise < Concurrent::Promise
|
15
|
+
public :on_fulfill, :on_reject
|
16
|
+
end
|
17
|
+
private_constant :Promise
|
18
|
+
|
19
|
+
class << self
|
20
|
+
# Creates a Task from a block
|
21
|
+
#
|
22
|
+
# @overload new(promise)
|
23
|
+
# @param promise [Promise]
|
24
|
+
# @return [Task]
|
25
|
+
#
|
26
|
+
# @overload new(&block)
|
27
|
+
# @param block [Proc] a task to run
|
28
|
+
# @return [Task]
|
29
|
+
#
|
30
|
+
def new(promise = nil, &block)
|
31
|
+
if promise
|
32
|
+
super(promise)
|
33
|
+
else
|
34
|
+
super(Promise.execute(&block))
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
# Creates a Task with the given executor
|
39
|
+
#
|
40
|
+
# @example providing an executor instance, using Ruby 2.5+ syntax
|
41
|
+
# IO = Concurrent::ThreadPoolExecutor.new
|
42
|
+
# Task[IO] { do_http_request }
|
43
|
+
#
|
44
|
+
# @example using a predefined executor
|
45
|
+
# Task[:fast] { do_quick_task }
|
46
|
+
#
|
47
|
+
# @param executor [Concurrent::AbstractExecutorService,Symbol] Either an executor instance
|
48
|
+
# or a name of predefined global
|
49
|
+
# from concurrent-ruby
|
50
|
+
# @return [Task]
|
51
|
+
def [](executor, &block)
|
52
|
+
new(Promise.execute(executor: executor, &block))
|
53
|
+
end
|
54
|
+
|
55
|
+
# Returns a complete task from the given value
|
56
|
+
#
|
57
|
+
# @overload pure(value)
|
58
|
+
# @param value [Object]
|
59
|
+
# @return [Task]
|
60
|
+
#
|
61
|
+
# @overload pure(&block)
|
62
|
+
# @param block [Proc]
|
63
|
+
# @return [Task]
|
64
|
+
#
|
65
|
+
def pure(value = Undefined, &block)
|
66
|
+
v = Undefined.default(value, block)
|
67
|
+
new(Promise.fulfill(v))
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
# @api private
|
72
|
+
attr_reader :promise
|
73
|
+
protected :promise
|
74
|
+
|
75
|
+
# @api private
|
76
|
+
def initialize(promise)
|
77
|
+
@promise = promise
|
78
|
+
end
|
79
|
+
|
80
|
+
# Retrieves the value of the computation.
|
81
|
+
# Blocks current thread if the underlying promise
|
82
|
+
# hasn't been complete yet.
|
83
|
+
# Throws an error if the computation failed.
|
84
|
+
#
|
85
|
+
# @return [Object]
|
86
|
+
# @api public
|
87
|
+
def value!
|
88
|
+
if promise.wait.fulfilled?
|
89
|
+
promise.value
|
90
|
+
else
|
91
|
+
raise promise.reason
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
# Lifts a block over the Task monad.
|
96
|
+
#
|
97
|
+
# @param block [Proc]
|
98
|
+
# @return [Task]
|
99
|
+
# @api public
|
100
|
+
def fmap(&block)
|
101
|
+
self.class.new(promise.then(&block))
|
102
|
+
end
|
103
|
+
|
104
|
+
# Composes two tasks to run one after another.
|
105
|
+
# A more common name is `then` exists as an alias.
|
106
|
+
#
|
107
|
+
# @param block [Proc] A block that yields the result of the current task
|
108
|
+
# and returns another task
|
109
|
+
# @return [Task]
|
110
|
+
def bind(&block)
|
111
|
+
self.class.new(promise.flat_map { |value| block.(value).promise })
|
112
|
+
end
|
113
|
+
alias_method :then, :bind
|
114
|
+
|
115
|
+
# Converts to Result. Blocks the current thread if required.
|
116
|
+
#
|
117
|
+
# @return [Result]
|
118
|
+
def to_result
|
119
|
+
if promise.wait.fulfilled?
|
120
|
+
Result::Success.new(promise.value)
|
121
|
+
else
|
122
|
+
Result::Failure.new(promise.reason, RightBiased::Left.trace_caller)
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
# Converts to Maybe. Blocks the current thread if required.
|
127
|
+
#
|
128
|
+
# @return [Maybe]
|
129
|
+
def to_maybe
|
130
|
+
if promise.wait.fulfilled?
|
131
|
+
Maybe::Some.new(promise.value)
|
132
|
+
else
|
133
|
+
Maybe::None.new(RightBiased::Left.trace_caller)
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
# @return [String]
|
138
|
+
def to_s
|
139
|
+
state = case promise.state
|
140
|
+
when :fulfilled
|
141
|
+
"value=#{ value!.inspect }"
|
142
|
+
when :rejected
|
143
|
+
"error=#{ promise.reason.inspect }"
|
144
|
+
else
|
145
|
+
'?'
|
146
|
+
end
|
147
|
+
|
148
|
+
"Task(#{ state })"
|
149
|
+
end
|
150
|
+
alias_method :inspect, :to_s
|
151
|
+
|
152
|
+
# Tranforms the error if the computation wasn't successful.
|
153
|
+
#
|
154
|
+
# @param block [Proc]
|
155
|
+
# @return [Task]
|
156
|
+
def or_fmap(&block)
|
157
|
+
self.class.new(promise.rescue(&block))
|
158
|
+
end
|
159
|
+
|
160
|
+
# Rescues the error with a block that returns another task.
|
161
|
+
#
|
162
|
+
# @param block [Proc]
|
163
|
+
# @return [Object]
|
164
|
+
def or(&block)
|
165
|
+
child = Promise.new(
|
166
|
+
parent: promise,
|
167
|
+
executor: Concurrent::ImmediateExecutor.new
|
168
|
+
)
|
169
|
+
|
170
|
+
promise.on_error do |v|
|
171
|
+
begin
|
172
|
+
inner = block.(v).promise
|
173
|
+
inner.execute
|
174
|
+
inner.on_success { |r| child.on_fulfill(r) }
|
175
|
+
inner.on_error { |e| child.on_reject(e) }
|
176
|
+
rescue => e
|
177
|
+
child.on_reject(e)
|
178
|
+
end
|
179
|
+
end
|
180
|
+
promise.on_success { |v| child.on_fulfill(v) }
|
181
|
+
|
182
|
+
self.class.new(child)
|
183
|
+
end
|
184
|
+
|
185
|
+
# Extracts the resulting value if the computation was successful
|
186
|
+
# otherwise yields the block and returns its result.
|
187
|
+
#
|
188
|
+
# @param block [Proc]
|
189
|
+
# @return [Object]
|
190
|
+
def value_or(&block)
|
191
|
+
promise.rescue(&block).wait.value
|
192
|
+
end
|
193
|
+
|
194
|
+
# Blocks the current thread until the task is complete.
|
195
|
+
#
|
196
|
+
# @return [Task]
|
197
|
+
def wait(timeout = nil)
|
198
|
+
promise.wait(timeout)
|
199
|
+
self
|
200
|
+
end
|
201
|
+
|
202
|
+
# Compares two tasks. Note, it works
|
203
|
+
# good enough only for complete tasks.
|
204
|
+
#
|
205
|
+
# @return [Boolean]
|
206
|
+
def ==(other)
|
207
|
+
return true if equal?(other)
|
208
|
+
return false unless self.class == other.class
|
209
|
+
compare_promises(promise, other.promise)
|
210
|
+
end
|
211
|
+
|
212
|
+
# Whether the computation is complete.
|
213
|
+
#
|
214
|
+
# @return [Boolean]
|
215
|
+
def complete?
|
216
|
+
promise.complete?
|
217
|
+
end
|
218
|
+
|
219
|
+
# @return [Class]
|
220
|
+
def monad
|
221
|
+
Task
|
222
|
+
end
|
223
|
+
|
224
|
+
# Returns self.
|
225
|
+
#
|
226
|
+
# @return [Maybe::Some, Maybe::None]
|
227
|
+
def to_monad
|
228
|
+
self
|
229
|
+
end
|
230
|
+
|
231
|
+
# Applies the stored value to the given argument.
|
232
|
+
#
|
233
|
+
# @example
|
234
|
+
# Task.
|
235
|
+
# pure { |x, y| x ** y }.
|
236
|
+
# apply(Task { 2 }).
|
237
|
+
# apply(Task { 3 }).
|
238
|
+
# to_maybe # => Some(8)
|
239
|
+
#
|
240
|
+
# @param val [Task]
|
241
|
+
# @return [Task]
|
242
|
+
def apply(val = Undefined)
|
243
|
+
arg = Undefined.default(val) { yield }
|
244
|
+
bind { |f| arg.fmap { |v| curry(f).(v) } }
|
245
|
+
end
|
246
|
+
|
247
|
+
private
|
248
|
+
|
249
|
+
# @api private
|
250
|
+
def curry(value)
|
251
|
+
if defined?(@curried)
|
252
|
+
if @curried[0].equal?(value)
|
253
|
+
@curried[1]
|
254
|
+
else
|
255
|
+
Curry.(value)
|
256
|
+
end
|
257
|
+
else
|
258
|
+
@curried = [value, Curry.(value)]
|
259
|
+
@curried[1]
|
260
|
+
end
|
261
|
+
end
|
262
|
+
|
263
|
+
# @api private
|
264
|
+
def compare_promises(x, y)
|
265
|
+
x.equal?(y) ||
|
266
|
+
x.fulfilled? && y.fulfilled? && x.value == y.value ||
|
267
|
+
x.rejected? && y.rejected? && x.reason == y.reason
|
268
|
+
end
|
269
|
+
|
270
|
+
# Task constructors.
|
271
|
+
#
|
272
|
+
# @api public
|
273
|
+
module Mixin
|
274
|
+
Task = Task # @private
|
275
|
+
|
276
|
+
# Created a mixin with the given executor injected.
|
277
|
+
#
|
278
|
+
# @param executor [Concurrent::AbstractExecutorService,Symbol]
|
279
|
+
# @return [Module]
|
280
|
+
def self.[](executor)
|
281
|
+
Module.new do
|
282
|
+
include Mixin
|
283
|
+
|
284
|
+
# Created a new Task with an injected executor.
|
285
|
+
#
|
286
|
+
# @param block [Proc]
|
287
|
+
# @return [Task]
|
288
|
+
define_method(:Task) do |&block|
|
289
|
+
Task[executor, &block]
|
290
|
+
end
|
291
|
+
end
|
292
|
+
end
|
293
|
+
|
294
|
+
# Task constructors
|
295
|
+
module Constructors
|
296
|
+
# Builds a new Task instance.
|
297
|
+
#
|
298
|
+
# @param block [Proc]
|
299
|
+
# @return Task
|
300
|
+
def Task(&block)
|
301
|
+
Task.new(&block)
|
302
|
+
end
|
303
|
+
end
|
304
|
+
|
305
|
+
include Constructors
|
306
|
+
end
|
307
|
+
end
|
308
|
+
end
|
309
|
+
end
|