2011-09-14 37 views
7

tôi phát hiện ra từ hạch hỏi rằngLàm thế nào để foo (& nil) hoạt động khác với foo (& "không phải là một proc")?

[1, 2, 3].each(&nil) 

không gây ra bất kỳ lỗi - nó chỉ trả về một điều tra viên.

Ngược lại,

[1, 2, 3].each(&"") 

tăng

TypeError: wrong argument type String (expected Proc) 

Ngoài ra, nguyên nhân &nil block_given? để trả về false

def block_given_tester 
    if block_given? 
    puts "Block given" 
    else 
    puts "Block not given" 
    end 
end 

block_given_tester(&nil) # => Block not given 

Nó không phải vì NilClass thực hiện to_proc - Tôi đã kiểm tra rdoc.

tôi có thể hiểu tại sao nó muốn được tốt đẹp để có &nil, nhưng tôi không chắc chắn cách nó được thực hiện. Đây có phải chỉ là một trong những cách nil có hành vi đặc biệt không được chia sẻ bởi các đối tượng khác không?

Trả lời

7

Câu trả lời có thể được tìm thấy bằng cách xem mã nguồn của Ruby.

Ruby 1,8:

Nhìn vào chức năng block_pass trong file eval.c. Lưu ý rằng nó xử lý nil đặc biệt từ các đối tượng Proc (macro NIL_P). Nếu hàm được chuyển một giá trị nil, nó sẽ đánh giá một khối trống (tôi nghĩ) và trả về. Mã ngay sau khi nó kiểm tra xem đối tượng có phải là đối tượng Proc (hàm rb_obj_is_proc) và tăng ngoại lệ "loại đối số sai (dự kiến ​​Proc") nếu không.

của Ruby 1.9.2:

Nhìn vào phương pháp caller_setup_args trong file vm_insnhelper.c. Nó chuyển đổi các proc với to_proc chỉ nếu nó không phải là không; nếu không, kiểm tra loại chuyển đổi và loại được bỏ qua.

+0

Tôi giả sử bạn đang xem một trong 1,8 chi nhánh không phải là một trong số 1.9 chi nhánh. –

+0

Vâng, đó là từ Ruby 1.8, vì đó là mã tôi có sẵn. Bây giờ tôi đang tải mã cho Ruby 1.9.2 để xem có bất cứ điều gì đã thay đổi không. –

+1

Tôi đã chỉnh sửa câu trả lời của mình cho Ruby 1.9.2. –

Các vấn đề liên quan