Issue #4610 has been updated by Joshua Ballanco.


Ok, making this a feature request for 2.0 sounds like a good idea.

Regarding the consistency argument, as I understand Currying (or at least the way that it is implemented in most other languages), the result of a Proc#curry call should be a chain of Proc's with arity 1 that return Proc's with arity 1 until all arguments have been satisfied. It would be nice if Ruby behaved similarly.

For example, in OCaml (which auto-curries functions):

 # let foo a b c =
 print_endline (String.concat ", " [a; b; c])
 ;;
 val foo : string -> string -> string -> unit = <fun>
 # foo "first" ;;
 - : string -> string -> unit = <fun>
 # foo "first" "second" ;;
 - : string -> unit = <fun>
 # foo "first" "second" "third" ;;
 first, second, third
 - : unit = ()
 
----------------------------------------
Feature #4610: Proc#curry behavior is inconsistent with lambdas containing default argument values
http://redmine.ruby-lang.org/issues/4610

Author: Joshua Ballanco
Status: Open
Priority: Normal
Assignee: 
Category: 
Target version: 2.0


If I curry a lambda with 3 arguments, then I can call three times with one argument each time to get the desired results:

ruby-1.9.2-p180 :001 > l = ->(a, b, c) { puts "#{a}, #{b}, #{c}" }
#<Proc:0x00000100963650@(irb):1 (lambda)>
ruby-1.9.2-p180 :002 > c = l.curry
#<Proc:0x0000010095c9e0 (lambda)>
ruby-1.9.2-p180 :003 > c.('one').('two').('three')
one, two, three
nil

However, if the lambda has default values and I curry it, the entire lambda is evaluated after the first #call:


ruby-1.9.2-p180 :004 > l = ->(a = 'ichi', b = 'ni', c = 'san') { puts "#{a}, #{b}, #{c}" }
#<Proc:0x00000100877b88@(irb):4 (lambda)>
ruby-1.9.2-p180 :005 > c = l.curry
#<Proc:0x0000010086b338 (lambda)>
ruby-1.9.2-p180 :006 > c.('one').('two').('three')
one, ni, san
NoMethodError: undefined method `call' for nil:NilClass

This behavior seem very inconsistent. Ideally, if I wanted to use the default argument at a certain position in a currie proc, I would just #call with no arguments, like so:

ruby-1.9.2-p180 :007 > c.('one').().('three')
#=> Propose that this result in: "one, ni, three"


-- 
http://redmine.ruby-lang.org