lab42_curry 0.1.1 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +100 -2
- data/lib/lab42/curry.rb +12 -9
- data/lib/lab42/curry/arg_compiler.rb +40 -40
- data/lib/lab42/curry/arg_compiler/phase2.rb +75 -0
- data/lib/lab42/curry/arg_compiler/positionals.rb +96 -0
- data/lib/lab42/curry/computed_arg.rb +18 -0
- data/lib/lab42/curry/currier.rb +61 -0
- data/lib/lab42/curry/errors.rb +2 -1
- data/lib/lab42/curry/version.rb +1 -1
- metadata +6 -3
- data/lib/lab42/curry/data.rb +0 -44
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 81a83bce0a791069efb5bf01049fb137367565cc1289d2824a43aae3b4336a72
|
4
|
+
data.tar.gz: 66479962f8bd6be1d89c29794fa7d09d1a84971520b8cf277804f6c722d60f9d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: aadb1fda7c8a06586ce81fbc43e6d3f21fa20ec7c56297265f6a8330cc088740f3c197f7eac25e76a5a7bfc94d8267b7bc31a267ceb1cdaf9657196ff12a6554
|
7
|
+
data.tar.gz: '08c4b31e4d94aa2cd8a943e52a753b330cfbfacc402ae5ba22cf5d1cb4caea222d4a11983e33f5da4a1f52898797a8d966d6cf3f50f15e3f167f11f2bdc96c89'
|
data/README.md
CHANGED
@@ -54,8 +54,8 @@ Then we see that
|
|
54
54
|
|
55
55
|
Given the total reorder form
|
56
56
|
```ruby
|
57
|
-
let(:twohundred_three) { curry(:adder, runtime_arg(
|
58
|
-
# now first argument is c (index
|
57
|
+
let(:twohundred_three) { curry(:adder, runtime_arg(1), 1, runtime_arg(0)) }
|
58
|
+
# now first argument is c (index 1) and second a (index 0) and b = 1
|
59
59
|
# Like Elixir's &adder(&2, 1, &1)
|
60
60
|
```
|
61
61
|
Then we have
|
@@ -134,8 +134,106 @@ But we can create a more lenient curry with `curry!`
|
|
134
134
|
.to eq([1, 2, 0, :blue])
|
135
135
|
```
|
136
136
|
|
137
|
+
### Context Currying Blocks
|
137
138
|
|
139
|
+
Often times it is the block which might be the fixed point in a series of computations, for
|
140
|
+
that reason we will curry a block
|
138
141
|
|
142
|
+
Given a function that takes a block
|
143
|
+
```ruby
|
144
|
+
let(:sub_with) { ->(a, b, &blk) { blk.(a - b) } }
|
145
|
+
let(:double_diff) { curry( sub_with ) { _1 * 2 } }
|
146
|
+
```
|
147
|
+
Then it does just that
|
148
|
+
```ruby
|
149
|
+
expect( double_diff.(22, 1) ).to eq(42)
|
150
|
+
```
|
151
|
+
And of course we can also curry a positional argument
|
152
|
+
```ruby
|
153
|
+
triple_dec = curry( sub_with, rt_arg, 1 ) { _1 * 3 }
|
154
|
+
expect( triple_dec.(15) ).to eq(42)
|
155
|
+
```
|
156
|
+
|
157
|
+
#### Context Currying on Unbound Methods
|
158
|
+
|
159
|
+
Can be a very useful exercise, we will see that `curry` creates a curred function that will bind when called
|
160
|
+
|
161
|
+
Given the classical map example:
|
162
|
+
```ruby
|
163
|
+
let(:incrementer) { curry(Enumerable.instance_method(:map)) { _1 + 1} }
|
164
|
+
```
|
165
|
+
|
166
|
+
Then we can use it by binding it to an `Enumerable` object
|
167
|
+
```ruby
|
168
|
+
expect( incrementer.([1, 2]) ).to eq([2, 3])
|
169
|
+
```
|
170
|
+
|
171
|
+
But we must not provide a block **again**
|
172
|
+
```ruby
|
173
|
+
expect{ incrementer.([]) {_1 + 2} }
|
174
|
+
.to raise_error(
|
175
|
+
Lab42::Curry::DuplicateBlock,
|
176
|
+
"block has already been curried")
|
177
|
+
```
|
178
|
+
|
179
|
+
This again can be authorized by using the more lenient `curry!` version
|
180
|
+
And therefor
|
181
|
+
```ruby
|
182
|
+
maybe_incrementer = curry!(Enumerable.instance_method(:map)) {_1 + 1}
|
183
|
+
expect( maybe_incrementer.([1, 2], &:itself) ).to eq([1, 2])
|
184
|
+
```
|
185
|
+
|
186
|
+
But of course we can also bind to unbound methods w/o a block
|
187
|
+
|
188
|
+
Given
|
189
|
+
```ruby
|
190
|
+
let(:length) { curry(String.instance_method(:size)) }
|
191
|
+
```
|
192
|
+
Then we can call it in a functional way
|
193
|
+
```ruby
|
194
|
+
expect( length.("") ).to be_zero
|
195
|
+
```
|
196
|
+
|
197
|
+
### Context Computed Arguments
|
198
|
+
|
199
|
+
Let us say we want to define a specialisation of a function
|
200
|
+
Given
|
201
|
+
```ruby
|
202
|
+
def add a, b, c
|
203
|
+
a + b + c
|
204
|
+
end
|
205
|
+
let(:adddiff) { curry(:add, comp{ _2 - _3}) }
|
206
|
+
```
|
207
|
+
Then the first parameter will be the diff of the second and third argument
|
208
|
+
```ruby
|
209
|
+
expect( adddiff.(21, 1) ).to eq(42)
|
210
|
+
```
|
211
|
+
|
212
|
+
When we specify a position for `comp` the computed argument gets this place
|
213
|
+
```ruby
|
214
|
+
def args *a
|
215
|
+
a
|
216
|
+
end
|
217
|
+
let(:sum_middle) { curry(:args, comp(1){ _1 + _3 } ) }
|
218
|
+
```
|
219
|
+
Then we get
|
220
|
+
```ruby
|
221
|
+
expect( sum_middle.(1, 2) ).to eq([1, 3, 2])
|
222
|
+
```
|
223
|
+
|
224
|
+
#### Context Computed Keywords
|
225
|
+
|
226
|
+
Given
|
227
|
+
```ruby
|
228
|
+
def kwds *, **k
|
229
|
+
k
|
230
|
+
end
|
231
|
+
let(:sum) { curry(:kwds, a: comp{ _1 + _2}) }
|
232
|
+
```
|
233
|
+
Then we can expect that sum corresponds
|
234
|
+
```ruby
|
235
|
+
expect( sum.(1, 2) ).to eq({a: 3})
|
236
|
+
```
|
139
237
|
# LICENSE
|
140
238
|
|
141
239
|
Copyright 2020,1 Robert Dober robert.dober@gmail.com
|
data/lib/lab42/curry.rb
CHANGED
@@ -1,18 +1,16 @@
|
|
1
|
-
require_relative "curry/data"
|
2
|
-
require_relative "curry/runtime_arg"
|
3
1
|
require_relative "curry/compiletime_args"
|
2
|
+
require_relative "curry/computed_arg"
|
3
|
+
require_relative "curry/currier"
|
4
|
+
require_relative "curry/runtime_arg"
|
4
5
|
|
5
6
|
module Lab42
|
6
7
|
module Curry
|
7
8
|
def curry(method_or_name, *curry_time_args, **curry_time_kwds, &blk)
|
8
|
-
|
9
|
-
curry_data.curried
|
9
|
+
Currier.new(method_or_name, curry_time_args, curry_time_kwds, context: self, &blk)
|
10
10
|
end
|
11
11
|
|
12
12
|
def curry!(method_or_name, *curry_time_args, **curry_time_kwds, &blk)
|
13
|
-
|
14
|
-
curry_data.allow_kwd_override = true
|
15
|
-
curry_data.curried
|
13
|
+
Currier.new(method_or_name, curry_time_args, curry_time_kwds, context: self, allow_override: true, &blk)
|
16
14
|
end
|
17
15
|
|
18
16
|
def compiletime_args(positions)
|
@@ -20,8 +18,13 @@ module Lab42
|
|
20
18
|
end
|
21
19
|
alias_method :ct_args, :compiletime_args
|
22
20
|
|
23
|
-
def
|
24
|
-
|
21
|
+
def compute_arg(position = nil, &blk)
|
22
|
+
ComputedArg.new(position, blk)
|
23
|
+
end
|
24
|
+
alias_method :comp, :compute_arg
|
25
|
+
|
26
|
+
def runtime_arg position=nil
|
27
|
+
RuntimeArg.new position
|
25
28
|
end
|
26
29
|
alias_method :rt_arg, :runtime_arg
|
27
30
|
end
|
@@ -1,76 +1,76 @@
|
|
1
|
-
require_relative '
|
1
|
+
require_relative 'arg_compiler/positionals'
|
2
|
+
require_relative 'arg_compiler/phase2'
|
2
3
|
require_relative 'compiletime_args'
|
4
|
+
require_relative 'computed_arg'
|
5
|
+
require_relative 'runtime_arg'
|
6
|
+
|
3
7
|
require_relative 'errors'
|
4
8
|
|
5
9
|
module Lab42
|
6
10
|
module Curry
|
7
11
|
class ArgCompiler
|
8
12
|
|
9
|
-
|
10
|
-
@__compiled_args__ ||= _compile_args(rt_args)
|
11
|
-
end
|
13
|
+
attr_reader :ct_blk
|
12
14
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
15
|
+
def allows_override?; @allow_override end
|
16
|
+
|
17
|
+
def compile(rt_args, rt_kwds, rt_blk)
|
18
|
+
Phase2.new(self, rt_args, rt_kwds, rt_blk).compile
|
17
19
|
end
|
18
20
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
@
|
21
|
+
#
|
22
|
+
# 0 based
|
23
|
+
#
|
24
|
+
def positionals
|
25
|
+
@__positionals__ ||= Positionals.new
|
24
26
|
end
|
25
27
|
|
26
|
-
def
|
27
|
-
|
28
|
+
def final_kwds
|
29
|
+
@__final_kwds__ ||= {}
|
28
30
|
end
|
29
31
|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
@
|
35
|
-
@
|
32
|
+
private
|
33
|
+
def initialize(ct_args, ct_kwds, allow_override:, &blk)
|
34
|
+
@allow_override = allow_override
|
35
|
+
@ct_args = ct_args
|
36
|
+
@ct_blk = blk
|
37
|
+
@ct_kwds = ct_kwds
|
38
|
+
|
39
|
+
_precompile!
|
36
40
|
end
|
37
41
|
|
38
|
-
def
|
42
|
+
def _ct_arg ct_arg
|
39
43
|
case ct_arg
|
40
44
|
when RuntimeArg
|
41
|
-
|
45
|
+
positionals.set_runtime_arg ct_arg
|
42
46
|
when CompiletimeArgs
|
43
47
|
_set_positions! ct_arg
|
48
|
+
when ComputedArg
|
49
|
+
positionals.set_computation ct_arg
|
44
50
|
else
|
45
51
|
_set_final! ct_arg
|
46
52
|
end
|
47
53
|
end
|
48
54
|
|
49
|
-
def
|
50
|
-
|
51
|
-
raise DuplicatePositionSpecification, "There is already a curried value for #{pos}" if @final.has_key?(pos)
|
52
|
-
@final[pos] = value
|
53
|
-
while @final.has_key?(@pos)
|
54
|
-
@pos += 1
|
55
|
-
end
|
55
|
+
def _ct_kwd((key, val))
|
56
|
+
final_kwds[key] = val
|
56
57
|
end
|
57
58
|
|
58
|
-
def
|
59
|
-
|
59
|
+
def _precompile!
|
60
|
+
@ct_args.each(&method(:_ct_arg))
|
61
|
+
@ct_kwds.each(&method(:_ct_kwd))
|
60
62
|
end
|
61
63
|
|
62
|
-
def
|
63
|
-
|
64
|
+
def _set_final! value, pos=nil
|
65
|
+
positionals.set_value! value, pos
|
64
66
|
end
|
65
67
|
|
66
|
-
def
|
67
|
-
|
68
|
-
@final[rt_arg_position] = @rt_args.shift
|
68
|
+
def _set_position!((position, value))
|
69
|
+
positionals.set_value! value, position
|
69
70
|
end
|
70
71
|
|
71
|
-
def
|
72
|
-
|
73
|
-
_set_final! RuntimeArg, position
|
72
|
+
def _set_positions! ct_arg
|
73
|
+
ct_arg.each(&method(:_set_position!))
|
74
74
|
end
|
75
75
|
|
76
76
|
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
require_relative '../errors'
|
2
|
+
require_relative 'positionals'
|
3
|
+
module Lab42
|
4
|
+
module Curry
|
5
|
+
class ArgCompiler
|
6
|
+
class Phase2
|
7
|
+
|
8
|
+
attr_reader :compiler, :rt_args, :rt_blk, :rt_kwds
|
9
|
+
|
10
|
+
# TODO: Easy, peasy sequential refactor
|
11
|
+
def compile
|
12
|
+
if rt_blk && compiler.ct_blk && !compiler.allows_override?
|
13
|
+
raise Lab42::Curry::DuplicateBlock, "block has already been curried"
|
14
|
+
end
|
15
|
+
@blk = rt_blk || compiler.ct_blk
|
16
|
+
@kwds = compiler.final_kwds.merge(rt_kwds){ |k, old, new|
|
17
|
+
raise Lab42::Curry::DuplicateKeywordArgument,
|
18
|
+
"keyword argument :#{k} is already defined with value #{old.inspect} cannot override with #{new.inspect}" unless compiler.allows_override?
|
19
|
+
new
|
20
|
+
}
|
21
|
+
@args = compiler.positionals.export_args
|
22
|
+
@first_free = 0
|
23
|
+
rt_args.each_with_index do |rt_arg, idx|
|
24
|
+
computed = compiler.positionals.computed(idx)
|
25
|
+
if computed
|
26
|
+
end
|
27
|
+
translated = compiler.positionals.translation(idx)
|
28
|
+
if translated
|
29
|
+
@args[translated] = rt_arg
|
30
|
+
else
|
31
|
+
# @args[idx + some_dynamic_offset] = rt_arg ???
|
32
|
+
_occupy_first_free rt_arg
|
33
|
+
end
|
34
|
+
end
|
35
|
+
compiler.positionals.computations do |idx, computed_arg|
|
36
|
+
@args[idx] = _compute(computed_arg)
|
37
|
+
end
|
38
|
+
@kwds.each do |kwd, val|
|
39
|
+
case val
|
40
|
+
when ComputedArg
|
41
|
+
@kwds[kwd] = _compute(val)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
# TODO: Raise ArgumentError if holes are left in @args, but for that reason we must make compiler.final_args compact
|
45
|
+
# and indicate wholes with RuntimeArg, not sure this is done same for holes in @kwds
|
46
|
+
[@args, @kwds, @blk]
|
47
|
+
end
|
48
|
+
|
49
|
+
private
|
50
|
+
|
51
|
+
def initialize(compiler, rt_args, rt_kwds, rt_blk)
|
52
|
+
@compiler = compiler
|
53
|
+
@rt_args = rt_args
|
54
|
+
@rt_blk = rt_blk
|
55
|
+
@rt_kwds = rt_kwds
|
56
|
+
end
|
57
|
+
|
58
|
+
def _compute computed_arg
|
59
|
+
computed_arg.(*@args, **@kwds)
|
60
|
+
end
|
61
|
+
|
62
|
+
def _occupy_first_free with_value
|
63
|
+
return @args << with_value unless @first_free
|
64
|
+
@first_free =
|
65
|
+
(@first_free..@args.size).find {|idx| @args[idx] == RuntimeArg}
|
66
|
+
if @first_free
|
67
|
+
@args[@first_free] = with_value
|
68
|
+
else
|
69
|
+
@args << with_value
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
@@ -0,0 +1,96 @@
|
|
1
|
+
require_relative '../errors'
|
2
|
+
require_relative '../runtime_arg'
|
3
|
+
# Represents the positionitional arguments as
|
4
|
+
# a hash idx -> value with operations to
|
5
|
+
# fill the "holes" with args provisioned
|
6
|
+
# at runtime.
|
7
|
+
# The filling of the holes is done at runtime
|
8
|
+
# by translating runtime argument indices with
|
9
|
+
# the @translations hash.
|
10
|
+
module Lab42
|
11
|
+
module Curry
|
12
|
+
class ArgCompiler
|
13
|
+
class Positionals
|
14
|
+
|
15
|
+
attr_reader :ct_pos, :rt_pos
|
16
|
+
|
17
|
+
def computations
|
18
|
+
@computations.each { |idx, comp| yield idx, comp }
|
19
|
+
end
|
20
|
+
|
21
|
+
def computed idx
|
22
|
+
@computations[idx]
|
23
|
+
end
|
24
|
+
|
25
|
+
def export_args
|
26
|
+
(0...(@args.keys.max&.succ||0))
|
27
|
+
.inject [] do |result, idx|
|
28
|
+
if @args.has_key?(idx)
|
29
|
+
result << @args[idx]
|
30
|
+
else
|
31
|
+
result << RuntimeArg
|
32
|
+
end
|
33
|
+
result
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def set_computation comp_arg
|
38
|
+
@args[comp_arg.position || ct_pos] = comp_arg.class
|
39
|
+
@computations[comp_arg.position || rt_pos] = comp_arg
|
40
|
+
end
|
41
|
+
|
42
|
+
# An rt_arg placeholder
|
43
|
+
def set_runtime_arg rt_arg
|
44
|
+
@args[ct_pos] = rt_arg.class
|
45
|
+
@translations[rt_arg.position || rt_pos] = ct_pos
|
46
|
+
_update_positions
|
47
|
+
end
|
48
|
+
|
49
|
+
# A curried value or computation, occurs from `ct_args` or literal values in which case `ct_pos` is `nil`
|
50
|
+
def set_value! value, ct_pos=nil
|
51
|
+
ct_pos ||= @ct_pos
|
52
|
+
raise Lab42::Curry::DuplicatePositionSpecification,
|
53
|
+
"There is already a curried value #{@args[ct_pos].inspect} at index #{ct_pos}" if _occupied?(ct_pos)
|
54
|
+
@args[ct_pos] = value
|
55
|
+
|
56
|
+
(@ct_pos..ct_pos.pred).each(&method(:_occupy))
|
57
|
+
# TODO: Need to check if we have to fill the holes with RuntimeArg
|
58
|
+
# and allow @ct_pos to point to present RuntimeArg values?
|
59
|
+
|
60
|
+
_update_positions
|
61
|
+
end
|
62
|
+
|
63
|
+
def translation idx
|
64
|
+
@translations[idx]
|
65
|
+
end
|
66
|
+
|
67
|
+
private
|
68
|
+
def initialize
|
69
|
+
@args = {}
|
70
|
+
@computations = {}
|
71
|
+
@ct_pos = 0
|
72
|
+
@rt_pos = 0
|
73
|
+
@translations = {}
|
74
|
+
end
|
75
|
+
|
76
|
+
def _occupied? key
|
77
|
+
@args.has_key?(key) && @args[key] != RuntimeArg
|
78
|
+
end
|
79
|
+
|
80
|
+
def _occupy idx
|
81
|
+
@args[idx] = RuntimeArg unless @args.has_key?(idx)
|
82
|
+
end
|
83
|
+
|
84
|
+
def _update_positions
|
85
|
+
while @args.has_key?(@ct_pos)
|
86
|
+
@ct_pos += 1
|
87
|
+
end
|
88
|
+
while @translations.has_key?(@rt_pos)
|
89
|
+
@rt_pos += 1
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module Lab42
|
2
|
+
module Curry
|
3
|
+
class ComputedArg
|
4
|
+
|
5
|
+
attr_reader :position
|
6
|
+
|
7
|
+
def call(*args, **kwds)
|
8
|
+
@blk.call(*args, **kwds)
|
9
|
+
end
|
10
|
+
|
11
|
+
private
|
12
|
+
def initialize(position, blk)
|
13
|
+
@blk = blk
|
14
|
+
@position = position
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
require_relative 'arg_compiler'
|
2
|
+
|
3
|
+
module Lab42
|
4
|
+
module Curry
|
5
|
+
class Currier
|
6
|
+
attr_reader :arg_compiler, :context, :ct_args, :ct_blk, :ct_kwds, :mthd
|
7
|
+
|
8
|
+
def call(*args, **kwds, &blk)
|
9
|
+
case mthd
|
10
|
+
when UnboundMethod
|
11
|
+
_bind_and_call(args, kwds, blk)
|
12
|
+
else
|
13
|
+
_just_call(args, kwds, blk)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def _bind_and_call(args, kwds, blk)
|
18
|
+
receiver = args.shift
|
19
|
+
mthd = @mthd.bind(receiver)
|
20
|
+
rt_args, rt_kwds, rt_blk = arg_compiler.compile(args, kwds, blk)
|
21
|
+
if rt_blk
|
22
|
+
mthd.(*rt_args, **rt_kwds, &rt_blk)
|
23
|
+
else
|
24
|
+
mthd.(*rt_args, **rt_kwds)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def _just_call(args, kwds, blk)
|
29
|
+
rt_args, rt_kwds, rt_blk = arg_compiler.compile(args, kwds, blk)
|
30
|
+
if rt_blk
|
31
|
+
mthd.(*rt_args, **rt_kwds, &rt_blk)
|
32
|
+
else
|
33
|
+
mthd.(*rt_args, **rt_kwds)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
private
|
38
|
+
def initialize(method_or_name, ct_args, ct_kwds, context:, allow_override: false, &ct_blk)
|
39
|
+
@allow_override = allow_override
|
40
|
+
@context = context
|
41
|
+
@ct_args = ct_args
|
42
|
+
@ct_blk = ct_blk
|
43
|
+
@ct_kwds = ct_kwds
|
44
|
+
|
45
|
+
@arg_compiler = ArgCompiler.new(ct_args, ct_kwds, allow_override: allow_override, &ct_blk)
|
46
|
+
|
47
|
+
_init_mthd method_or_name
|
48
|
+
end
|
49
|
+
|
50
|
+
def _init_mthd method_or_name
|
51
|
+
@mthd =
|
52
|
+
case method_or_name
|
53
|
+
when Symbol
|
54
|
+
context.method(method_or_name)
|
55
|
+
else
|
56
|
+
method_or_name
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
data/lib/lab42/curry/errors.rb
CHANGED
@@ -1,7 +1,8 @@
|
|
1
1
|
module Lab42
|
2
2
|
module Curry
|
3
|
-
|
3
|
+
DuplicateBlock = Class.new RuntimeError
|
4
4
|
DuplicateKeywordArgument = Class.new RuntimeError
|
5
|
+
DuplicatePositionSpecification = Class.new RuntimeError
|
5
6
|
MissingRuntimeArg = Class.new RuntimeError
|
6
7
|
end
|
7
8
|
end
|
data/lib/lab42/curry/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: lab42_curry
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Robert Dober
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2021-01-02 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: pry
|
@@ -63,8 +63,11 @@ files:
|
|
63
63
|
- README.md
|
64
64
|
- lib/lab42/curry.rb
|
65
65
|
- lib/lab42/curry/arg_compiler.rb
|
66
|
+
- lib/lab42/curry/arg_compiler/phase2.rb
|
67
|
+
- lib/lab42/curry/arg_compiler/positionals.rb
|
66
68
|
- lib/lab42/curry/compiletime_args.rb
|
67
|
-
- lib/lab42/curry/
|
69
|
+
- lib/lab42/curry/computed_arg.rb
|
70
|
+
- lib/lab42/curry/currier.rb
|
68
71
|
- lib/lab42/curry/errors.rb
|
69
72
|
- lib/lab42/curry/runtime_arg.rb
|
70
73
|
- lib/lab42/curry/version.rb
|
data/lib/lab42/curry/data.rb
DELETED
@@ -1,44 +0,0 @@
|
|
1
|
-
require_relative 'arg_compiler'
|
2
|
-
|
3
|
-
module Lab42
|
4
|
-
module Curry
|
5
|
-
class Data
|
6
|
-
attr_accessor :allow_kwd_override
|
7
|
-
attr_reader :context, :ct_args, :ct_kwds, :curried
|
8
|
-
|
9
|
-
private
|
10
|
-
def initialize(ctxt, method_or_name, *curry_time_args, **curry_time_kwds, &blk)
|
11
|
-
@allow_kwd_override
|
12
|
-
@context = ctxt
|
13
|
-
@ct_args = curry_time_args
|
14
|
-
@ct_kwds = curry_time_kwds
|
15
|
-
|
16
|
-
@mthd =
|
17
|
-
case method_or_name
|
18
|
-
when Symbol
|
19
|
-
context.method(method_or_name)
|
20
|
-
else
|
21
|
-
method_or_name
|
22
|
-
end
|
23
|
-
|
24
|
-
@arg_compiler = ArgCompiler.new(ct_args)
|
25
|
-
_curry(&blk)
|
26
|
-
end
|
27
|
-
|
28
|
-
def _curry(&blk)
|
29
|
-
@curried = ->(*rt_args, **rt_kwds) do
|
30
|
-
@mthd.(
|
31
|
-
*@arg_compiler.compile_args(rt_args),
|
32
|
-
**@ct_kwds.merge(rt_kwds) { |kwd, old_val, new_val|
|
33
|
-
if allow_kwd_override
|
34
|
-
new_val
|
35
|
-
else
|
36
|
-
raise DuplicateKeywordArgument, "keyword argument #{kwd.inspect} is already defined with value #{old_val.inspect} cannot override with #{new_val.inspect}"
|
37
|
-
end
|
38
|
-
}
|
39
|
-
)
|
40
|
-
end
|
41
|
-
end
|
42
|
-
end
|
43
|
-
end
|
44
|
-
end
|