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

Comments

Projects
None yet
2 participants
@phluid61
Copy link
Contributor

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

This comment has been minimized.

Copy link
Member

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

This comment has been minimized.

Copy link
Member

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

This comment has been minimized.

Copy link
Member

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

This comment has been minimized.

Copy link
Member

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.

@headius headius closed this in 7270345 Feb 26, 2014

@tak1n tak1n referenced this issue May 23, 2015

Merged

fix Proc#curry #3406

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.