J. Gary
J. Gary

Reputation: 9

Ruby - Return A Proc.Call As Variable?

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

Answers (3)

Simple Lime
Simple Lime

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 calling 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

Vijay Agrawal
Vijay Agrawal

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

Peter Camilleri
Peter Camilleri

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

Related Questions