dry-monads 0.4.0 → 1.0.0.beta1
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 +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
|