Skip to content

Commit e5def49

Browse files
committedMay 23, 2015
ported over jruby's fix for Proc#curry, this closes #2951
1 parent 621953b commit e5def49

File tree

2 files changed

+31
-14
lines changed

2 files changed

+31
-14
lines changed
 

Diff for: ‎kernel/common/proc.rb

+18-11
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,23 @@ def self.__from_block__(env)
1414
end
1515
end
1616

17+
def self.__make_curry_proc__(proc, passed, arity)
18+
is_lambda = proc.lambda?
19+
passed.freeze
20+
21+
__send__((is_lambda ? :lambda : :proc)) do |*argv, &passed_proc|
22+
my_passed = passed + argv
23+
if my_passed.length < arity
24+
if !passed_proc.nil?
25+
warn "#{caller[0]}: given block not used"
26+
end
27+
__make_curry_proc__(proc, my_passed, arity)
28+
else
29+
proc.call(*my_passed)
30+
end
31+
end
32+
end
33+
1734
def self.new(*args)
1835
env = nil
1936

@@ -94,17 +111,7 @@ def curry(curried_arity = nil)
94111

95112
args = []
96113

97-
my_self = self
98-
m = lambda? ? :lambda : :proc
99-
f = __send__(m) {|*x|
100-
call_args = args + x
101-
if call_args.length >= my_self.arity
102-
my_self[*call_args]
103-
else
104-
args = call_args
105-
f
106-
end
107-
}
114+
f = Proc.__make_curry_proc__(self, [], arity)
108115

109116
f.singleton_class.send(:define_method, :binding) {
110117
raise ArgumentError, "cannot create binding from f proc"

Diff for: ‎spec/ruby/core/proc/curry_spec.rb

+13-3
Original file line numberDiff line numberDiff line change
@@ -59,17 +59,17 @@
5959
l = lambda { |*a| }
6060
l.curry.arity.should == -1
6161
end
62-
62+
6363
it "produces Procs that raise ArgumentError for #binding" do
6464
lambda do
6565
@proc_add.curry.binding
6666
end.should raise_error(ArgumentError)
6767
end
68-
68+
6969
it "produces Procs that return [[:rest]] for #parameters" do
7070
@proc_add.curry.parameters.should == [[:rest]]
7171
end
72-
72+
7373
it "produces Procs that return nil for #source_location" do
7474
@proc_add.curry.source_location.should == nil
7575
end
@@ -79,6 +79,16 @@
7979

8080
instance_exec(3, &curried).should == 6
8181
end
82+
83+
it "combines arguments and calculates incoming arity accurately for successively currying" do
84+
l = lambda{|a,b,c| a+b+c }
85+
l1 = l.curry.call(1)
86+
# the l1 currying seems unnecessary, but it triggered the original issue
87+
l2 = l1.curry.call(2)
88+
89+
l2.curry.call(3).should == 6
90+
l1.curry.call(2,3).should == 6
91+
end
8292
end
8393

8494
describe "Proc#curry with arity argument" do

0 commit comments

Comments
 (0)
Please sign in to comment.