dry-types 1.2.1 → 1.5.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/CHANGELOG.md +405 -221
- data/LICENSE +1 -1
- data/README.md +14 -13
- data/dry-types.gemspec +26 -31
- data/lib/dry-types.rb +1 -1
- data/lib/dry/types.rb +55 -40
- data/lib/dry/types/any.rb +2 -2
- data/lib/dry/types/array.rb +2 -2
- data/lib/dry/types/array/constructor.rb +1 -1
- data/lib/dry/types/array/member.rb +1 -1
- data/lib/dry/types/builder.rb +70 -18
- data/lib/dry/types/builder_methods.rb +6 -3
- data/lib/dry/types/coercions.rb +6 -17
- data/lib/dry/types/coercions/json.rb +22 -5
- data/lib/dry/types/coercions/params.rb +21 -4
- data/lib/dry/types/compiler.rb +10 -10
- data/lib/dry/types/constrained.rb +6 -10
- data/lib/dry/types/constraints.rb +3 -3
- data/lib/dry/types/constructor.rb +40 -7
- data/lib/dry/types/constructor/function.rb +47 -32
- data/lib/dry/types/constructor/wrapper.rb +94 -0
- data/lib/dry/types/container.rb +1 -1
- data/lib/dry/types/core.rb +15 -13
- data/lib/dry/types/decorator.rb +2 -9
- data/lib/dry/types/default.rb +15 -3
- data/lib/dry/types/enum.rb +4 -4
- data/lib/dry/types/errors.rb +6 -6
- data/lib/dry/types/extensions.rb +2 -2
- data/lib/dry/types/extensions/maybe.rb +17 -17
- data/lib/dry/types/extensions/monads.rb +1 -1
- data/lib/dry/types/fn_container.rb +1 -1
- data/lib/dry/types/hash.rb +9 -15
- data/lib/dry/types/hash/constructor.rb +1 -1
- data/lib/dry/types/inflector.rb +1 -1
- data/lib/dry/types/json.rb +15 -15
- data/lib/dry/types/lax.rb +4 -7
- data/lib/dry/types/map.rb +2 -2
- data/lib/dry/types/meta.rb +3 -3
- data/lib/dry/types/module.rb +6 -6
- data/lib/dry/types/nominal.rb +11 -12
- data/lib/dry/types/params.rb +31 -28
- data/lib/dry/types/predicate_inferrer.rb +52 -11
- data/lib/dry/types/predicate_registry.rb +1 -1
- data/lib/dry/types/primitive_inferrer.rb +1 -1
- data/lib/dry/types/printer.rb +25 -25
- data/lib/dry/types/result.rb +3 -3
- data/lib/dry/types/schema.rb +26 -13
- data/lib/dry/types/schema/key.rb +20 -7
- data/lib/dry/types/spec/types.rb +65 -42
- data/lib/dry/types/sum.rb +6 -6
- data/lib/dry/types/type.rb +1 -1
- data/lib/dry/types/version.rb +1 -1
- metadata +27 -84
- data/.codeclimate.yml +0 -12
- data/.github/ISSUE_TEMPLATE/----please-don-t-ask-for-support-via-issues.md +0 -10
- data/.github/ISSUE_TEMPLATE/---bug-report.md +0 -34
- data/.github/ISSUE_TEMPLATE/---feature-request.md +0 -18
- data/.github/workflows/custom_ci.yml +0 -76
- data/.github/workflows/docsite.yml +0 -34
- data/.github/workflows/sync_configs.yml +0 -34
- data/.gitignore +0 -11
- data/.rspec +0 -4
- data/.rubocop.yml +0 -89
- data/.yardopts +0 -9
- data/CODE_OF_CONDUCT.md +0 -13
- data/CONTRIBUTING.md +0 -29
- data/Gemfile +0 -32
- data/Rakefile +0 -22
- data/benchmarks/hash_schemas.rb +0 -55
- data/benchmarks/lax_schema.rb +0 -15
- data/benchmarks/profile_invalid_input.rb +0 -15
- data/benchmarks/profile_lax_schema_valid.rb +0 -16
- data/benchmarks/profile_valid_input.rb +0 -15
- data/benchmarks/schema_valid_vs_invalid.rb +0 -21
- data/benchmarks/setup.rb +0 -17
- data/docsite/source/array-with-member.html.md +0 -13
- data/docsite/source/built-in-types.html.md +0 -116
- data/docsite/source/constraints.html.md +0 -31
- data/docsite/source/custom-types.html.md +0 -93
- data/docsite/source/default-values.html.md +0 -91
- data/docsite/source/enum.html.md +0 -69
- data/docsite/source/extensions.html.md +0 -15
- data/docsite/source/extensions/maybe.html.md +0 -57
- data/docsite/source/extensions/monads.html.md +0 -61
- data/docsite/source/getting-started.html.md +0 -57
- data/docsite/source/hash-schemas.html.md +0 -169
- data/docsite/source/index.html.md +0 -156
- data/docsite/source/map.html.md +0 -17
- data/docsite/source/optional-values.html.md +0 -35
- data/docsite/source/sum.html.md +0 -21
@@ -4,7 +4,6 @@ module Dry
|
|
4
4
|
module Types
|
5
5
|
# Common API for building type objects in a convenient way
|
6
6
|
#
|
7
|
-
# rubocop:disable Naming/MethodName
|
8
7
|
#
|
9
8
|
# @api public
|
10
9
|
module BuilderMethods
|
@@ -83,7 +82,11 @@ module Dry
|
|
83
82
|
# @return [Dry::Types::Type]
|
84
83
|
def Constructor(klass, cons = nil, &block)
|
85
84
|
if klass.is_a?(Type)
|
86
|
-
|
85
|
+
if cons || block
|
86
|
+
klass.constructor(cons || block)
|
87
|
+
else
|
88
|
+
klass
|
89
|
+
end
|
87
90
|
else
|
88
91
|
Nominal(klass).constructor(cons || block || klass.method(:new))
|
89
92
|
end
|
@@ -129,7 +132,7 @@ module Dry
|
|
129
132
|
#
|
130
133
|
# @return [Dry::Types::Contrained]
|
131
134
|
def Interface(*methods)
|
132
|
-
methods.reduce(Types[
|
135
|
+
methods.reduce(Types["nominal.any"]) do |type, method|
|
133
136
|
type.constrained(respond_to: method)
|
134
137
|
end
|
135
138
|
end
|
data/lib/dry/types/coercions.rb
CHANGED
@@ -8,23 +8,6 @@ module Dry
|
|
8
8
|
module Coercions
|
9
9
|
include Dry::Core::Constants
|
10
10
|
|
11
|
-
# @param [String, Object] input
|
12
|
-
#
|
13
|
-
# @return [nil] if the input is an empty string or nil
|
14
|
-
#
|
15
|
-
# @raise CoercionError
|
16
|
-
#
|
17
|
-
# @api public
|
18
|
-
def to_nil(input, &_block)
|
19
|
-
if input.nil? || empty_str?(input)
|
20
|
-
nil
|
21
|
-
elsif block_given?
|
22
|
-
yield
|
23
|
-
else
|
24
|
-
raise CoercionError, "#{input.inspect} is not nil"
|
25
|
-
end
|
26
|
-
end
|
27
|
-
|
28
11
|
# @param [#to_str, Object] input
|
29
12
|
#
|
30
13
|
# @return [Date, Object]
|
@@ -39,6 +22,8 @@ module Dry
|
|
39
22
|
rescue ArgumentError, RangeError => e
|
40
23
|
CoercionError.handle(e, &block)
|
41
24
|
end
|
25
|
+
elsif input.is_a?(::Date)
|
26
|
+
input
|
42
27
|
elsif block_given?
|
43
28
|
yield
|
44
29
|
else
|
@@ -60,6 +45,8 @@ module Dry
|
|
60
45
|
rescue ArgumentError => e
|
61
46
|
CoercionError.handle(e, &block)
|
62
47
|
end
|
48
|
+
elsif input.is_a?(::DateTime)
|
49
|
+
input
|
63
50
|
elsif block_given?
|
64
51
|
yield
|
65
52
|
else
|
@@ -81,6 +68,8 @@ module Dry
|
|
81
68
|
rescue ArgumentError => e
|
82
69
|
CoercionError.handle(e, &block)
|
83
70
|
end
|
71
|
+
elsif input.is_a?(::Time)
|
72
|
+
input
|
84
73
|
elsif block_given?
|
85
74
|
yield
|
86
75
|
else
|
@@ -1,9 +1,9 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
4
|
-
require
|
5
|
-
require
|
6
|
-
require
|
3
|
+
require "date"
|
4
|
+
require "bigdecimal"
|
5
|
+
require "bigdecimal/util"
|
6
|
+
require "time"
|
7
7
|
|
8
8
|
module Dry
|
9
9
|
module Types
|
@@ -14,6 +14,23 @@ module Dry
|
|
14
14
|
module JSON
|
15
15
|
extend Coercions
|
16
16
|
|
17
|
+
# @param [Object] input
|
18
|
+
#
|
19
|
+
# @return [nil] if the input is nil
|
20
|
+
#
|
21
|
+
# @raise CoercionError
|
22
|
+
#
|
23
|
+
# @api public
|
24
|
+
def self.to_nil(input, &_block)
|
25
|
+
if input.nil?
|
26
|
+
nil
|
27
|
+
elsif block_given?
|
28
|
+
yield
|
29
|
+
else
|
30
|
+
raise CoercionError, "#{input.inspect} is not nil"
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
17
34
|
# @param [#to_d, Object] input
|
18
35
|
#
|
19
36
|
# @return [BigDecimal,nil]
|
@@ -21,7 +38,7 @@ module Dry
|
|
21
38
|
# @raise CoercionError
|
22
39
|
#
|
23
40
|
# @api public
|
24
|
-
def self.to_decimal(input, &
|
41
|
+
def self.to_decimal(input, &_block)
|
25
42
|
if input.is_a?(::Float)
|
26
43
|
input.to_d
|
27
44
|
else
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
4
|
-
require
|
3
|
+
require "bigdecimal"
|
4
|
+
require "bigdecimal/util"
|
5
5
|
|
6
6
|
module Dry
|
7
7
|
module Types
|
@@ -14,10 +14,27 @@ module Dry
|
|
14
14
|
FALSE_VALUES = %w[0 off Off OFF f false False FALSE F n no No NO N].freeze
|
15
15
|
BOOLEAN_MAP = ::Hash[
|
16
16
|
TRUE_VALUES.product([true]) + FALSE_VALUES.product([false])
|
17
|
-
].freeze
|
17
|
+
].merge(true => true, false => false).freeze
|
18
18
|
|
19
19
|
extend Coercions
|
20
20
|
|
21
|
+
# @param [Object] input
|
22
|
+
#
|
23
|
+
# @return [nil] if the input is an empty string or nil
|
24
|
+
#
|
25
|
+
# @raise CoercionError
|
26
|
+
#
|
27
|
+
# @api public
|
28
|
+
def self.to_nil(input, &_block)
|
29
|
+
if input.nil? || empty_str?(input)
|
30
|
+
nil
|
31
|
+
elsif block_given?
|
32
|
+
yield
|
33
|
+
else
|
34
|
+
raise CoercionError, "#{input.inspect} is not nil"
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
21
38
|
# @param [String, Object] input
|
22
39
|
#
|
23
40
|
# @return [Boolean,Object]
|
@@ -95,7 +112,7 @@ module Dry
|
|
95
112
|
# @raise CoercionError
|
96
113
|
#
|
97
114
|
# @api public
|
98
|
-
def self.to_decimal(input, &
|
115
|
+
def self.to_decimal(input, &_block)
|
99
116
|
to_float(input) do
|
100
117
|
if block_given?
|
101
118
|
return yield
|
data/lib/dry/types/compiler.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
3
|
+
require "dry/core/deprecations"
|
4
4
|
|
5
5
|
module Dry
|
6
6
|
module Types
|
@@ -63,37 +63,37 @@ module Dry
|
|
63
63
|
def visit_array(node)
|
64
64
|
member, meta = node
|
65
65
|
member = member.is_a?(Class) ? member : visit(member)
|
66
|
-
registry[
|
66
|
+
registry["nominal.array"].of(member).meta(meta)
|
67
67
|
end
|
68
68
|
|
69
69
|
def visit_hash(node)
|
70
70
|
opts, meta = node
|
71
|
-
registry[
|
71
|
+
registry["nominal.hash"].with(**opts, meta: meta)
|
72
72
|
end
|
73
73
|
|
74
74
|
def visit_schema(node)
|
75
75
|
keys, options, meta = node
|
76
|
-
registry[
|
76
|
+
registry["nominal.hash"].schema(keys.map { |key| visit(key) }).with(**options, meta: meta)
|
77
77
|
end
|
78
78
|
|
79
79
|
def visit_json_hash(node)
|
80
80
|
keys, meta = node
|
81
|
-
registry[
|
81
|
+
registry["json.hash"].schema(keys.map { |key| visit(key) }, meta)
|
82
82
|
end
|
83
83
|
|
84
84
|
def visit_json_array(node)
|
85
85
|
member, meta = node
|
86
|
-
registry[
|
86
|
+
registry["json.array"].of(visit(member)).meta(meta)
|
87
87
|
end
|
88
88
|
|
89
89
|
def visit_params_hash(node)
|
90
90
|
keys, meta = node
|
91
|
-
registry[
|
91
|
+
registry["params.hash"].schema(keys.map { |key| visit(key) }, meta)
|
92
92
|
end
|
93
93
|
|
94
94
|
def visit_params_array(node)
|
95
95
|
member, meta = node
|
96
|
-
registry[
|
96
|
+
registry["params.array"].of(visit(member)).meta(meta)
|
97
97
|
end
|
98
98
|
|
99
99
|
def visit_key(node)
|
@@ -108,11 +108,11 @@ module Dry
|
|
108
108
|
|
109
109
|
def visit_map(node)
|
110
110
|
key_type, value_type, meta = node
|
111
|
-
registry[
|
111
|
+
registry["nominal.hash"].map(visit(key_type), visit(value_type)).meta(meta)
|
112
112
|
end
|
113
113
|
|
114
114
|
def visit_any(meta)
|
115
|
-
registry[
|
115
|
+
registry["any"].meta(meta)
|
116
116
|
end
|
117
117
|
|
118
118
|
def compile_fn(fn)
|
@@ -1,8 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
4
|
-
require
|
5
|
-
require
|
3
|
+
require "dry/types/decorator"
|
4
|
+
require "dry/types/constraints"
|
5
|
+
require "dry/types/constrained/coercible"
|
6
6
|
|
7
7
|
module Dry
|
8
8
|
module Types
|
@@ -14,7 +14,7 @@ module Dry
|
|
14
14
|
include Decorator
|
15
15
|
include Builder
|
16
16
|
include Printable
|
17
|
-
include Dry::Equalizer(:type, :rule, inspect: false)
|
17
|
+
include Dry::Equalizer(:type, :rule, inspect: false, immutable: true)
|
18
18
|
|
19
19
|
# @return [Dry::Logic::Rule]
|
20
20
|
attr_reader :rule
|
@@ -29,11 +29,9 @@ module Dry
|
|
29
29
|
@rule = options.fetch(:rule)
|
30
30
|
end
|
31
31
|
|
32
|
-
# @api private
|
33
|
-
#
|
34
32
|
# @return [Object]
|
35
33
|
#
|
36
|
-
# @api
|
34
|
+
# @api private
|
37
35
|
def call_unsafe(input)
|
38
36
|
result = rule.(input)
|
39
37
|
|
@@ -44,11 +42,9 @@ module Dry
|
|
44
42
|
end
|
45
43
|
end
|
46
44
|
|
47
|
-
# @api private
|
48
|
-
#
|
49
45
|
# @return [Object]
|
50
46
|
#
|
51
|
-
# @api
|
47
|
+
# @api private
|
52
48
|
def call_safe(input, &block)
|
53
49
|
if rule[input]
|
54
50
|
type.call_safe(input, &block)
|
@@ -1,8 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
4
|
-
require
|
5
|
-
require
|
3
|
+
require "dry/logic/rule_compiler"
|
4
|
+
require "dry/logic/predicates"
|
5
|
+
require "dry/logic/rule/predicate"
|
6
6
|
|
7
7
|
module Dry
|
8
8
|
# Helper methods for constraint types
|
@@ -1,7 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
4
|
-
require
|
3
|
+
require "dry/types/fn_container"
|
4
|
+
require "dry/types/constructor/function"
|
5
|
+
require "dry/types/constructor/wrapper"
|
5
6
|
|
6
7
|
module Dry
|
7
8
|
module Types
|
@@ -10,7 +11,7 @@ module Dry
|
|
10
11
|
#
|
11
12
|
# @api public
|
12
13
|
class Constructor < Nominal
|
13
|
-
include Dry::Equalizer(:type, :options, inspect: false)
|
14
|
+
include Dry::Equalizer(:type, :options, inspect: false, immutable: true)
|
14
15
|
|
15
16
|
# @return [#call]
|
16
17
|
attr_reader :fn
|
@@ -30,6 +31,32 @@ module Dry
|
|
30
31
|
super(type, **options, fn: Function[options.fetch(:fn, block)])
|
31
32
|
end
|
32
33
|
|
34
|
+
# @param [Builder, Object] input
|
35
|
+
# @param [Hash] options
|
36
|
+
# @param [#call, nil] block
|
37
|
+
#
|
38
|
+
# @api public
|
39
|
+
def self.[](type, fn:, **options)
|
40
|
+
function = Function[fn]
|
41
|
+
|
42
|
+
if function.wrapper?
|
43
|
+
wrapper_type.new(type, fn: function, **options)
|
44
|
+
else
|
45
|
+
new(type, fn: function, **options)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
# @api private
|
50
|
+
def self.wrapper_type
|
51
|
+
@wrapper_type ||= begin
|
52
|
+
if self < Wrapper
|
53
|
+
self
|
54
|
+
else
|
55
|
+
const_set(:Wrapping, ::Class.new(self).include(Wrapper))
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
33
60
|
# Instantiate a new constructor type instance
|
34
61
|
#
|
35
62
|
# @param [Type] type
|
@@ -85,7 +112,13 @@ module Dry
|
|
85
112
|
#
|
86
113
|
# @api public
|
87
114
|
def constructor(new_fn = nil, **options, &block)
|
88
|
-
|
115
|
+
next_fn = Function[new_fn || block]
|
116
|
+
|
117
|
+
if next_fn.wrapper?
|
118
|
+
self.class.wrapper_type.new(with(**options), fn: next_fn)
|
119
|
+
else
|
120
|
+
with(**options, fn: fn >> next_fn)
|
121
|
+
end
|
89
122
|
end
|
90
123
|
alias_method :append, :constructor
|
91
124
|
alias_method :>>, :constructor
|
@@ -123,7 +156,7 @@ module Dry
|
|
123
156
|
# @return [Lax]
|
124
157
|
# @api public
|
125
158
|
def lax
|
126
|
-
Lax.new(
|
159
|
+
Lax.new(constructor_type[type.lax, **options])
|
127
160
|
end
|
128
161
|
|
129
162
|
# Wrap the type with a proc
|
@@ -157,8 +190,8 @@ module Dry
|
|
157
190
|
if type.respond_to?(method)
|
158
191
|
response = type.public_send(method, *args, &block)
|
159
192
|
|
160
|
-
if response.is_a?(Type) && type.class
|
161
|
-
response.constructor_type
|
193
|
+
if response.is_a?(Type) && type.class.equal?(response.class)
|
194
|
+
response.constructor_type[response, **options]
|
162
195
|
else
|
163
196
|
response
|
164
197
|
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
3
|
+
require "concurrent/map"
|
4
4
|
|
5
5
|
module Dry
|
6
6
|
module Types
|
@@ -15,7 +15,7 @@ module Dry
|
|
15
15
|
class Safe < Function
|
16
16
|
def call(input, &block)
|
17
17
|
@fn.(input, &block)
|
18
|
-
rescue NoMethodError, TypeError, ArgumentError => e
|
18
|
+
rescue ::NoMethodError, ::TypeError, ::ArgumentError => e
|
19
19
|
CoercionError.handle(e, &block)
|
20
20
|
end
|
21
21
|
end
|
@@ -30,10 +30,14 @@ module Dry
|
|
30
30
|
#
|
31
31
|
# @return [Function]
|
32
32
|
def self.call_class(method, public, safe)
|
33
|
-
@cache.fetch_or_store([method, public, safe]
|
33
|
+
@cache.fetch_or_store([method, public, safe]) do
|
34
34
|
if public
|
35
35
|
::Class.new(PublicCall) do
|
36
36
|
include PublicCall.call_interface(method, safe)
|
37
|
+
|
38
|
+
define_method(:__to_s__) do
|
39
|
+
"#<PublicCall for :#{method}>"
|
40
|
+
end
|
37
41
|
end
|
38
42
|
elsif safe
|
39
43
|
PrivateCall
|
@@ -53,7 +57,7 @@ module Dry
|
|
53
57
|
#
|
54
58
|
# @return [::Module]
|
55
59
|
def self.call_interface(method, safe)
|
56
|
-
@interfaces.fetch_or_store([method, safe]
|
60
|
+
@interfaces.fetch_or_store([method, safe]) do
|
57
61
|
::Module.new do
|
58
62
|
if safe
|
59
63
|
module_eval(<<~RUBY, __FILE__, __LINE__ + 1)
|
@@ -65,7 +69,7 @@ module Dry
|
|
65
69
|
module_eval(<<~RUBY, __FILE__, __LINE__ + 1)
|
66
70
|
def call(input, &block)
|
67
71
|
@target.#{method}(input)
|
68
|
-
rescue NoMethodError, TypeError, ArgumentError => error
|
72
|
+
rescue ::NoMethodError, ::TypeError, ::ArgumentError => error
|
69
73
|
CoercionError.handle(error, &block)
|
70
74
|
end
|
71
75
|
RUBY
|
@@ -90,7 +94,7 @@ module Dry
|
|
90
94
|
class PrivateSafeCall < PrivateCall
|
91
95
|
def call(input, &block)
|
92
96
|
@target.send(@name, input)
|
93
|
-
rescue NoMethodError, TypeError, ArgumentError => e
|
97
|
+
rescue ::NoMethodError, ::TypeError, ::ArgumentError => e
|
94
98
|
CoercionError.handle(e, &block)
|
95
99
|
end
|
96
100
|
end
|
@@ -116,15 +120,31 @@ module Dry
|
|
116
120
|
end
|
117
121
|
end
|
118
122
|
|
123
|
+
class Wrapper < Function
|
124
|
+
# @return [Object]
|
125
|
+
def call(input, type, &block)
|
126
|
+
@fn.(input, type, &block)
|
127
|
+
rescue ::NoMethodError, ::TypeError, ::ArgumentError => e
|
128
|
+
CoercionError.handle(e, &block)
|
129
|
+
end
|
130
|
+
alias_method :[], :call
|
131
|
+
|
132
|
+
def arity
|
133
|
+
2
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
119
137
|
# Choose or build specialized invokation code for a callable
|
120
138
|
#
|
121
139
|
# @param [#call] fn
|
122
140
|
# @return [Function]
|
123
141
|
def self.[](fn)
|
124
|
-
raise ArgumentError,
|
142
|
+
raise ::ArgumentError, "Missing constructor block" if fn.nil?
|
125
143
|
|
126
144
|
if fn.is_a?(Function)
|
127
145
|
fn
|
146
|
+
elsif fn.respond_to?(:arity) && fn.arity.equal?(2)
|
147
|
+
Wrapper.new(fn)
|
128
148
|
elsif fn.is_a?(::Method)
|
129
149
|
MethodCall[fn, yields_block?(fn)]
|
130
150
|
elsif yields_block?(fn)
|
@@ -146,7 +166,7 @@ module Dry
|
|
146
166
|
last_arg.equal?(:block)
|
147
167
|
end
|
148
168
|
|
149
|
-
include Dry::Equalizer(:fn)
|
169
|
+
include ::Dry::Equalizer(:fn, immutable: true)
|
150
170
|
|
151
171
|
attr_reader :fn
|
152
172
|
|
@@ -160,39 +180,34 @@ module Dry
|
|
160
180
|
end
|
161
181
|
alias_method :[], :call
|
162
182
|
|
183
|
+
# @return [Integer]
|
184
|
+
def arity
|
185
|
+
1
|
186
|
+
end
|
187
|
+
|
188
|
+
def wrapper?
|
189
|
+
arity.equal?(2)
|
190
|
+
end
|
191
|
+
|
163
192
|
# @return [Array]
|
164
193
|
def to_ast
|
165
194
|
if fn.is_a?(::Proc)
|
166
|
-
[:id,
|
195
|
+
[:id, FnContainer.register(fn)]
|
167
196
|
else
|
168
197
|
[:callable, fn]
|
169
198
|
end
|
170
199
|
end
|
171
200
|
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
end
|
178
|
-
|
179
|
-
# @return [Function]
|
180
|
-
def <<(other)
|
181
|
-
proc = other.is_a?(::Proc) ? other : other.fn
|
182
|
-
Function[@fn << proc]
|
183
|
-
end
|
184
|
-
else
|
185
|
-
# @return [Function]
|
186
|
-
def >>(other)
|
187
|
-
proc = other.is_a?(::Proc) ? other : other.fn
|
188
|
-
Function[-> x { proc[@fn[x]] }]
|
189
|
-
end
|
201
|
+
# @return [Function]
|
202
|
+
def >>(other)
|
203
|
+
f = Function[other]
|
204
|
+
Function[-> x, &b { f.(self.(x, &b), &b) }]
|
205
|
+
end
|
190
206
|
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
end
|
207
|
+
# @return [Function]
|
208
|
+
def <<(other)
|
209
|
+
f = Function[other]
|
210
|
+
Function[-> x, &b { self.(f.(x, &b), &b) }]
|
196
211
|
end
|
197
212
|
end
|
198
213
|
end
|