lab42_curry 0.1.1 → 0.2.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/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
|