Please consider the following different ways to define method m
:
Method 1:
class C def m; yield; end end
Method 2:
class C def initialize (class << self; self; end).class_eval do define_method(:m){|&b| b.call } end end end
Method 3:
class C def initialize (class << self; self; end).class_eval do define_method(:m){puts block_given?; yield} end end end
Then I can invoke m
using Object#send
.
o = C.new
o.send(:m) {puts 'test'}
While calling m
using Method 1 or Method 2 works fine, Method 3 gives this error:
no block given (yield) (LocalJumpError)
I understand that a block is not an object, but instead just a part of method calling syntax and you cannot pass an implicit block from one function to another without writing something obscure like this:
def printer
yield
end
def proxy
printer &Proc.new
end
proxy { puts "&Proc.new probably creates Proc object from block"}
But in that case, why does Method 1 work? It would be awesome to get an answer which would explain what's happening under the hood.