yield gọi block ẩn mà method nhận được; &block chuyển block thành một object Proc để có thể lưu, truyền tiếp hoặc kiểm tra.
ruby
def with_retry_implicit
yield # implicit block, nothing allocated
end
def with_retry_explicit(&block)
raise ArgumentError, 'block required' unless block
Retryer.new.run(&block) # can be stored and forwarded
endKhác biệt cần biết:
- yield không cấp phát object; &block tạo một Proc mỗi lần gọi method → chậm hơn một chút, đáng quan tâm ở đường dẫn nóng.
- Chỉ có &block mới truyền block sang method khác được (other_method(&block)), hoặc lưu vào biến instance để gọi sau.
- Gọi yield khi không có block sẽ ném LocalJumpError. Kiểm tra trước bằng block_given? (với block ẩn) hoặc unless block (với block tường minh).
ruby
def each_item
return to_enum(:each_item) unless block_given? # usable without a block
@items.each { |i| yield i }
endChọn: mặc định dùng yield — ngắn và nhanh hơn.
Chuyển sang &block khi cần truyền tiếp, lưu lại, hoặc kiểm tra block.