Reputation:
How can I yield two diferent blocks in the same method
the example code:
def by_two(n,a)
yield n
yield a
end
proc1 = proc {|x| p x * 2}
proc2 = proc {|x| x + 100}
by_two(10, 300, &proc1, &proc2)
the error is such -
main.rb:7: syntax error, unexpected ',', expecting ')'
by_two(10, 300, &proc1, &proc2)
Any suggestions where and what is wrong? Thanks
Upvotes: 5
Views: 3498
Reputation: 369633
Blocks are a lightweight way of passing a single anonymous procedure to a method. So, by definition, there cannot be two blocks passed to a method. It's not just semantically impossible, it isn't even possible syntactically.
Ruby does support first-class procedures in the form of Proc
s, however, and since those are just objects like any other object, you can pass as many of them as you want:
def by_two(n, a, proc1, proc2)
proc1.(n)
proc2.(a)
end
proc1 = proc {|x| p x * 2}
proc2 = proc {|x| x + 100}
by_two(10, 300, proc1, proc2)
# 20
# => 400
Since the introduction of lambda literals in Ruby 1.9, Proc
s are almost as syntactically lightweight as blocks, so there is not a big difference anymore:
by_two(10, 300, -> x { p x * 2 }, -> x { x + 100 })
# 20
# => 400
Upvotes: 10
Reputation: 6867
The answer to your question is: You cannot do it if you insist on blocks! Ruby does not support multiple blocks per method. A way to go around this is to pass two procs as variables like this:
def by_two(n,a, proc1=nil, proc2=nil)
if proc1 || proc2
proc1.yield n if proc1
puts proc2.yield a if proc2
else
puts "no procs"
end
end
proc1 = proc {|x| p x * 2}
proc2 = proc {|x| x + 100}
by_two(10, 300, proc1, proc2)
by_two(10, 300, proc1)
by_two(10, 300)
Output:
20
400
20
no procs
Another possibility is this:
NO_OP = proc {}
def by_two(n,a, proc1=NO_OP, proc2=NO_OP)
if proc1 == NO_OP && proc2 == NO_OP
puts "no procs"
else
proc1.yield n
proc2.yield a
end
end
proc1 = proc {|x| p x * 2}
proc2 = proc {|x| p x + 100}
by_two(10, 300, proc1, proc2)
by_two(10, 300, proc1)
by_two(10, 300)
It has the same output.
Upvotes: 4
Reputation: 168269
You cannot yield two blocks in a method.
But you can take two procs.
def by_two(n, a, pr1, pr2)
pr1.call(n)
pr2.call(a)
end
by_two(10, 300, proc1, proc2)
Upvotes: 9