Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

unexpected ArgumentError in curried Proc #1523

Closed
phluid61 opened this issue Feb 22, 2014 · 4 comments
Closed

unexpected ArgumentError in curried Proc #1523

phluid61 opened this issue Feb 22, 2014 · 4 comments

Comments

@phluid61
Copy link
Contributor

@phluid61 phluid61 commented Feb 22, 2014

This Travis run shows an unexpected ArgumentError in Proc#call after sequential calls to #curry and #call

Effective code is:

l = lambda{|a,b,c| a+b+c }
l1 = l.curry.call(1)
l2 = l1.curry.call(2)
l2.curry.call(3) #=> 6
l1.curry.call(2,3) #=> ArgumentError

Ruby version is: jruby 1.7.9 (1.9.3p392) 2014-02-10 87b108a on Java HotSpot(TM) 64-Bit Server VM 1.7.0_51-b13 [linux-amd64]

@headius
Copy link
Member

@headius headius commented Feb 22, 2014

Confirmed. Same error in Rubinius, with whom we share a pure-Ruby implementation of curry: https://github.com/jruby/jruby/blob/master/core/src/main/ruby/jruby/kernel/proc.rb

It would appear something's not quite right there.

@headius
Copy link
Member

@headius headius commented Feb 22, 2014

It appears there's some interaction between the multiple curries. If I remove the curries unrelated to the error path, it works fine.

@headius
Copy link
Member

@headius headius commented Feb 22, 2014

Here's a patch that fixes the problem, and this may be sufficient for now. I believe the primary change is isolating arity and args from each level of currying by funneling them through this other method.

diff --git a/core/src/main/ruby/jruby/kernel19/proc.rb b/core/src/main/ruby/jruby/kernel19/proc.rb
index 617d68b..9a3c38d 100644
--- a/core/src/main/ruby/jruby/kernel19/proc.rb
+++ b/core/src/main/ruby/jruby/kernel19/proc.rb
@@ -16,19 +16,7 @@ class Proc
       end
     end

-    args = []
-
-    my_self = self
-    m = lambda? ? :lambda : :proc
-    f = __send__(m) {|*x|
-      call_args = args + x
-      if call_args.length >= my_self.arity
-        my_self[*call_args]
-      else
-        args = call_args
-        f
-      end
-    }
+    f = Proc.__make_curry_proc__(self, [], arity)

     f.singleton_class.send(:define_method, :binding) {
       raise ArgumentError, "cannot create binding from f proc"
@@ -44,4 +32,21 @@ class Proc

     f
   end
+
+  def self.__make_curry_proc__(proc, passed, arity)
+    is_lambda = proc.lambda?
+    passed.freeze
+
+    __send__((is_lambda ? :lambda : :proc)) do |*argv, &passed_proc|
+      my_passed = passed + argv
+      if my_passed.length < arity
+        if !passed_proc.nil?
+          warn "#{caller[0]}: given block not used"
+        end
+        __make_curry_proc__(proc, my_passed, arity)
+      else
+        proc.call(*my_passed)
+      end
+    end
+  end
 end

This logic is ported from Ruby 2.1.

I will probably go ahead with this fix and then look at eliminating the existing singleton logic (unrelated to this bug).

@headius
Copy link
Member

@headius headius commented Feb 22, 2014

I've pushed my fix to the post-11 branch, which I'll merge to jruby-1_7 and master once 1.7.11 has been released.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
2 participants