2012-08-22 40 views
5

Khi tôi viết phương pháp mà phải mất một khối không bắt buộc, tôi thường sử dụng một cái gì đó giống nhưTại sao `block_given?` Không hoạt động trong phương pháp được xác định động này?

block.call if block_given? 

Tuy nhiên, trong phương pháp định nghĩa tự động như hình dưới đây, block_given? dường như không làm việc.

class Foo 
    %w[bar baz].each do |method_name| 
    define_singleton_method(method_name) do |&block| 
     puts "Was #{method_name} given a block? #{block_given?}" 
     puts block.call 
    end 
    end 
end 

Foo.bar { puts 'I am a block' } 

Khối được gọi như mong đợi, nhưng block_given? trả về giá trị sai.

Tại sao điều này?

Trả lời

9

Chặn đóng cửa, vì vậy, chúng nhớ các biến cục bộ (ví dụ: method_name). Họ cũng nhớ khối: yieldblock_given? đang tìm kiếm khối đã hoạt động tại thời điểm define_method được gọi, chứ không phải khối được chuyển đến bar. Không có một, do đó, khối trả về sai.

Một minh họa tốt hơn của việc này là

def create_method 
    define_singleton_method('foo') do |&block| 
    puts "Was given a block? #{block_given?}" 
    puts yield 
    puts block.call 
    end 
end 

create_method {'block passed to create_method'} 
foo {'block passed to the created method'} 

mà kết quả đầu ra

Was given a block? true 
block passed to create_method 
block passed to the created method 
Các vấn đề liên quan