diff options
Diffstat (limited to 'spec/ruby/core/proc/curry_spec.rb')
| -rw-r--r-- | spec/ruby/core/proc/curry_spec.rb | 179 |
1 files changed, 179 insertions, 0 deletions
diff --git a/spec/ruby/core/proc/curry_spec.rb b/spec/ruby/core/proc/curry_spec.rb new file mode 100644 index 0000000000..de13983ca6 --- /dev/null +++ b/spec/ruby/core/proc/curry_spec.rb @@ -0,0 +1,179 @@ +require_relative '../../spec_helper' + +describe "Proc#curry" do + before :each do + @proc_add = Proc.new {|x,y,z| (x||0) + (y||0) + (z||0) } + @lambda_add = -> x, y, z { (x||0) + (y||0) + (z||0) } + end + + it "returns a Proc when called on a proc" do + p = proc { true } + p.curry.should.instance_of?(Proc) + end + + it "returns a Proc when called on a lambda" do + p = -> { true } + p.curry.should.instance_of?(Proc) + end + + it "calls the curried proc with the arguments if sufficient arguments have been given" do + @proc_add.curry[1][2][3].should == 6 + @lambda_add.curry[1][2][3].should == 6 + end + + it "returns a Proc that consumes the remainder of the arguments unless sufficient arguments have been given" do + proc2 = @proc_add.curry[1][2] + proc2.should.instance_of?(Proc) + proc2.call(3).should == 6 + + lambda2 = @lambda_add.curry[1][2] + lambda2.should.instance_of?(Proc) + lambda2.call(3).should == 6 + + @proc_add.curry.call(1,2,3).should == 6 + @lambda_add.curry.call(1,2,3).should == 6 + end + + it "can be called multiple times on the same Proc" do + @proc_add.curry + -> { @proc_add.curry }.should_not.raise + + @lambda_add.curry + -> { @lambda_add.curry }.should_not.raise + end + + it "can be passed superfluous arguments if created from a proc" do + @proc_add.curry[1,2,3,4].should == 6 + + @proc_add.curry[1,2].curry[3,4,5,6].should == 6 + end + + it "raises an ArgumentError if passed superfluous arguments when created from a lambda" do + -> { @lambda_add.curry[1,2,3,4] }.should.raise(ArgumentError) + -> { @lambda_add.curry[1,2].curry[3,4,5,6] }.should.raise(ArgumentError) + end + + it "returns Procs with arities of -1" do + @proc_add.curry.arity.should == -1 + @lambda_add.curry.arity.should == -1 + l = -> *a { } + l.curry.arity.should == -1 + end + + it "produces Procs that raise ArgumentError for #binding" do + -> do + @proc_add.curry.binding + end.should.raise(ArgumentError) + end + + it "produces Procs that return [[:rest]] for #parameters" do + @proc_add.curry.parameters.should == [[:rest]] + end + + it "produces Procs that return nil for #source_location" do + @proc_add.curry.source_location.should == nil + end + + it "produces Procs that can be passed as the block for instance_exec" do + curried = @proc_add.curry.call(1, 2) + + instance_exec(3, &curried).should == 6 + end + + it "combines arguments and calculates incoming arity accurately for successively currying" do + l = -> a, b, c { a+b+c } + l1 = l.curry.call(1) + # the l1 currying seems unnecessary, but it triggered the original issue + l2 = l1.curry.call(2) + + l2.curry.call(3).should == 6 + l1.curry.call(2,3).should == 6 + end +end + +describe "Proc#curry with arity argument" do + before :each do + @proc_add = proc { |x,y,z| (x||0) + (y||0) + (z||0) } + @lambda_add = -> x, y, z { (x||0) + (y||0) + (z||0) } + end + + it "accepts an optional Integer argument for the arity" do + -> { @proc_add.curry(3) }.should_not.raise + -> { @lambda_add.curry(3) }.should_not.raise + end + + it "returns a Proc when called on a proc" do + @proc_add.curry(3).should.instance_of?(Proc) + end + + it "returns a Proc when called on a lambda" do + @lambda_add.curry(3).should.instance_of?(Proc) + end + + # [ruby-core:24127] + it "retains the lambda-ness of the Proc on which its called" do + @lambda_add.curry(3).lambda?.should == true + @proc_add.curry(3).lambda?.should == false + end + + it "raises an ArgumentError if called on a lambda that requires more than _arity_ arguments" do + -> { @lambda_add.curry(2) }.should.raise(ArgumentError) + -> { -> x, y, z, *more{}.curry(2) }.should.raise(ArgumentError) + end + + it 'returns a Proc if called on a lambda that requires fewer than _arity_ arguments but may take more' do + -> a, b, c, d=nil, e=nil {}.curry(4).should.instance_of?(Proc) + -> a, b, c, d=nil, *e {}.curry(4).should.instance_of?(Proc) + -> a, b, c, *d {}.curry(4).should.instance_of?(Proc) + end + + it "raises an ArgumentError if called on a lambda that requires fewer than _arity_ arguments" do + -> { @lambda_add.curry(4) }.should.raise(ArgumentError) + -> { -> { true }.curry(1) }.should.raise(ArgumentError) + -> { -> a, b=nil {}.curry(5) }.should.raise(ArgumentError) + -> { -> a, &b {}.curry(2) }.should.raise(ArgumentError) + -> { -> a, b=nil, &c {}.curry(3) }.should.raise(ArgumentError) + end + + it "calls the curried proc with the arguments if _arity_ arguments have been given" do + @proc_add.curry(3)[1][2][3].should == 6 + @lambda_add.curry(3)[1][2][3].should == 6 + end + + it "returns a Proc that consumes the remainder of the arguments when fewer than _arity_ arguments are given" do + proc2 = @proc_add.curry(3)[1][2] + proc2.should.instance_of?(Proc) + proc2.call(3).should == 6 + + lambda2 = @lambda_add.curry(3)[1][2] + lambda2.should.instance_of?(Proc) + lambda2.call(3).should == 6 + end + + it "can be specified multiple times on the same Proc" do + @proc_add.curry(2) + -> { @proc_add.curry(1) }.should_not.raise + + @lambda_add.curry(3) + -> { @lambda_add.curry(3) }.should_not.raise + end + + it "can be passed more than _arity_ arguments if created from a proc" do + @proc_add.curry(3)[1,2,3,4].should == 6 + + @proc_add.curry(3)[1,2].curry(3)[3,4,5,6].should == 6 + end + + it "raises an ArgumentError if passed more than _arity_ arguments when created from a lambda" do + -> { @lambda_add.curry(3)[1,2,3,4] }.should.raise(ArgumentError) + -> { @lambda_add.curry(3)[1,2].curry(3)[3,4,5,6] }.should.raise(ArgumentError) + end + + it "returns Procs with arities of -1 regardless of the value of _arity_" do + @proc_add.curry(1).arity.should == -1 + @proc_add.curry(2).arity.should == -1 + @lambda_add.curry(3).arity.should == -1 + l = -> *a { } + l.curry(3).arity.should == -1 + end +end |
