2010-01-24 35 views
28

Tại sao nó rằng đoạn mã sau chạy tốtcủa Ruby In Tiêm Đỗ Cú pháp

p (1..1000).inject(0) { |sum, i| 
    sum + i 
} 

Nhưng, đoạn code sau đưa ra một lỗi

p (1..1000).inject(0) do |sum, i| 
    sum + i 
end 

warning: do not use Fixnums as Symbols 
in `inject': 0 is not a symbol (ArgumentError) 

họ không nên được tương đương?

Trả lời

34

Khối được viết bằng cách sử dụng dấu ngoặc nhọn liên kết với phương pháp tiêm, đó là ý định của bạn và nó sẽ hoạt động tốt.

Tuy nhiên, khối được đóng gói trong khối kết thúc/kết thúc, sẽ liên kết với phương thức p. Bởi vì điều này, các cuộc gọi tiêm không có một khối liên quan. Trong trường hợp này, tiêm sẽ diễn giải đối số, trong trường hợp này là 0, là tên phương thức để gọi trên mọi đối tượng. Bacuase 0 không phải là một biểu tượng có thể được chuyển đổi thành một cuộc gọi phương thức, điều này sẽ mang lại một cảnh báo.

6

này trông giống như một ảnh hưởng của sự khác biệt trong ràng buộc giữa việc phải làm/kết thúc và dấu ngoặc:

ngoặc, được sử dụng khi bạn đang ở trên, sẽ liên kết với các chức năng cuối cùng xích trong khi làm/kết thúc sẽ ràng buộc để là người đầu tiên.

Tôi nghĩ rằng đó là một cách kỳ lạ để nói nó, nhưng về cơ bản trường hợp đầu tiên là chuyển khối tới hàm 'inject', trong khi thứ hai thực sự đang cố chuyển khối tới phương thức đầu tiên 'p'.

+1

"trong khi thứ hai là thực sự cố gắng để vượt qua các khối để phương pháp đầu tiên (1 ..1000). " Làm cho rằng "để phương pháp đầu tiên' p' "và bạn là chính xác. – sepp2k

+0

Tôi đã sửa nó. bỏ qua điều đó trong đoạn mã trên ngay từ cái nhìn đầu tiên! – Pete

6

Sự cố xảy ra với số p ngay từ đầu. Nếu bạn bỏ qua những bạn sẽ thấy rằng cả hai hoạt động tốt:

# Works! 
[5, 6, 7].inject(0) do |sum, i| # Correctly binds to `inject`. 
    sum + i 
end 

# Works too! 
[5, 6, 7].inject(0) { |sum, i| # Correctly binds to `inject`. 
    sum + i 
} 

Nhưng điều này sẽ không làm việc:

# Kablammo! "p" came first, so it gets first dibs on your do..end block. 
# Now inject has no block to bind to! 
p [5, 6, 7].inject(0) do |sum, i| # Binds to `p` -- not what you wanted. 
    sum + i 
end 
Các vấn đề liên quan