Reputation: 2616
I'm trying to learn about blocks and procs and I feel like this should be doable, but so far I haven't been successful.
What I'd like:
def main_action(generic_variable, block)
generic_variable += 1 # I do more interesting stuff than this in my version
yield(generic_variable)
end
main_action(3, {|num| num + 5 })
Or something similar.
The closest I found was http://mudge.name/2011/01/26/passing-blocks-in-ruby-without-block.html which seemed to require creating a passing method to send the blocks around:
class Monkey
# Monkey.tell_ape { "ook!" }
# ape: ook!
# => nil
def self.tell_ape(&block)
tell("ape", &block)
end
def self.tell(name, &block)
puts "#{name}: #{block.call}"
end
end
If I use the same passing method set up in my code I can get it to work, but it seems like unnecessary code. I tried calling Monkey.tell("ape", { "ook!" })
directly, but got syntax error, unexpected '}', expecting tASSOC
Is it possible to send a variable and a block (or proc, I'm not picky) to a function in one call? Also, if you have time, what's going on above? Why doesn't that work?
Upvotes: 2
Views: 1919
Reputation: 2616
Based on sawa's answer I was able to recreate the function in the question (Monkey.tell
) using a block and proc. Here they are in case anyone else finds them useful!
def tell_proc(name, proc)
puts "#{name}: #{proc.call('ook')}"
end
tell_proc('ape', ->(sound) { sound + "!" })
def tell_block(name, &block)
puts "#{name}: #{block.call('ook')}"
end
tell_block('ape') {|sound| sound + "!" }
Upvotes: 2
Reputation: 168071
You seem to be confusing blocks and procs. A block is not a ruby object. You cannot pass it like
foo(args, block)
The only way to pass it is foo(args){...}
or foo(args) do ... end
. However, in method definition, you can receive a block, convert it into a proc, and accept it as one of its arguments like this:
def foo(args, &block)
...
end
On the other hand, You can pass a proc object as an argument like
foo(args, proc)
There are several ways to create a proc object, and a literal that is close to the block literal is the lambda: ->{...}
, but it is different from the block syntax {...}
. Using this, you can do
foo(args, ->{...})
but not
foo(args, {...})
unless {...}
is a hash.
Upvotes: 5