Reputation: 9
I'm trying to create a Ruby method that: 1. accepts as input a proc which accepts two arguments and 2. returns as output a proc which takes one argument (the other argument being passed in with the first proc.)
Code below. Everything I've read about how Ruby handles functional scope indicates that I should be able to return a proc.call as a variable, and I don't understand why I'm getting an "unexpected return" error (reproduced below the code)
(I'm obviously a beginning Rubyist...my experience has mostly been in JavaScript, where the mechanics of doing this sort of thing are, I think, much more intuitive.)
--
def partial (proc1, val1)
return Proc.new {|val2| return proc1.call(val1,val2)}
end
adder = Proc.new {|a,b| a + b}
sum_five = partial(adder,5)
sum_five.call(10) # -- expecting 15
# unexpected return
# (repl):13:in `block in partial'
# (repl):20:in `<main>'
Upvotes: 0
Views: 1067
Reputation: 11035
Although I don't understand it's name, Ruby already has a method, Proc#curry
, that does this:
adder = Proc.new {|a,b| a + b}
sum_five = adder.curry.call(5)
sum_five.call(10) # => 15
sum_five.call(2) # => 7
just watch out, because curry
takes an optional argument, which is the number of arguments it should expect before call
ing the initial proc, so if you pass it the argument you want as the "default" it'll work weird:
adder = Proc.new {|a,b| a + b}
sum_five = adder.curry(5) # NOTE: This is incorrect
sum_five.call(1) # => returns a Proc
sum_five[1][2][3][4][5] # => 3 (the first 2 arguments got passed, the rest ignored)
Upvotes: 0
Reputation: 1683
Shorter/cleaner ruby syntax:
def composer(proc1, val1)
-> (val2) { proc1.call(val1, val2) }
end
adder = -> (a,b) { a + b }
sum_five = composer(adder, 5)
sum_five.call(10)
Upvotes: 0
Reputation: 1902
In Ruby, procs and lambdas treat return differently.
Procs are designed to work within other Ruby control structures, so in that context a return is from the control structure. Lambdas are much more like stand-alone methods, so return returns from the lambda. You get an error because the proc has no context to return from.
Try this:
def partial (proc1, val1)
return lambda {|val2| return proc1.call(val1,val2)}
end
adder = Proc.new {|a,b| a + b}
sum_five = partial(adder,5)
puts sum_five.call(10) # -- expecting 15
Upvotes: 2