2010-11-21 30 views
30

Có ai đó có thể giải thích cho tôi về việc Ruby sử dụng các ký tự ống trong một khối không? Tôi hiểu rằng nó có chứa một tên biến sẽ được gán dữ liệu khi nó lặp lại. Nhưng cái này gọi là gì? Có thể có nhiều hơn một biến bên trong đường ống không? Bất cứ điều gì khác tôi nên biết về nó? Bất kỳ liên kết tốt nào để có thêm thông tin về nó?Ai đó có thể giải thích việc Ruby sử dụng các ký tự ống trong một khối không?

Ví dụ:

25.times { | i | puts i } 
+0

Câu hỏi liên quan: http://stackoverflow.com/questions/665576/what-are-those-pipe-symbols-for-in-ruby –

Trả lời

27

Niềng răng xác định một chức năng ẩn danh, được gọi là một khối. Các thẻ giữa các đường ống là các đối số của khối này. Số lượng đối số bắt buộc phụ thuộc vào cách khối được sử dụng. Mỗi lần khối được đánh giá, phương thức yêu cầu khối sẽ chuyển một giá trị dựa trên đối tượng đang gọi nó.

Cũng giống như xác định phương thức, chỉ có nó không được lưu trữ ngoài phương thức chấp nhận một khối.

Ví dụ:

def my_print(i) 
    puts i 
end 

sẽ làm điều tương tự như thế này khi thực hiện:

{|i| puts i} 

sự khác biệt duy nhất là các khối được định nghĩa một cách nhanh chóng và không được lưu trữ.

Ví dụ 2: Các câu sau đây là tương đương

25.times &method(:my_print) 

25.times {|i| puts i} 

Chúng tôi sử dụng các khối ẩn danh vì đa số các chức năng thông qua như là một khối thường cụ thể đối với tình hình của bạn và không đáng định để tái sử dụng.

Vậy điều gì xảy ra khi phương thức chấp nhận một khối? Điều đó phụ thuộc vào phương pháp.Các phương thức chấp nhận một khối sẽ gọi nó bằng cách truyền các giá trị từ đối tượng gọi của chúng theo cách được xác định rõ. Những gì được trả lại phụ thuộc vào phương thức yêu cầu khối.

Ví dụ: Trong 25.times {|i| puts i}. Số lần gọi khối một lần cho mỗi giá trị giữa 0 và giá trị của người gọi, chuyển giá trị vào khối dưới dạng biến tạm thời i. Times trả về giá trị của đối tượng gọi. Trong trường hợp này 25.

Hãy xem phương thức chấp nhận một khối có hai đối số.

{:key1 => "value1", :key2 => "value2"}.each {|key,value| 
    puts "This key is: #{key}. Its value is #{value}" 
} 

Trong trường hợp này, mỗi lệnh gọi khối cho mỗi cặp khóa/giá trị chuyển khóa làm đối số thứ nhất và giá trị làm đối số thứ hai.

+1

& my_print là cú pháp không hợp lệ, ý của bạn là & phương pháp (: my_print) – horseyguy

+0

Bạn đang phải lan can. Tôi đã không có thời gian để kiểm tra ví dụ đó, tôi biết rằng & được sử dụng để điều trị giá trị của một biến như một Proc. Tôi đã quên rằng các phương thức không chứa các giá trị. Tôi đã cập nhật ví dụ. Cảm ơn bạn đã chỉ ra điều đó. – EmFi

+4

Cảm ơn lời giải thích tốt về khái niệm kỳ quặc như vậy đối với những người trong chúng ta đến từ Java. – Andy

5

Các ống chỉ định đối số được điền bằng giá trị của các chức năng mà các cuộc gọi block của bạn. Có thể có số không hoặc nhiều hơn, và số lượng bạn nên sử dụng tùy thuộc vào phương thức bạn gọi.

Ví dụ: each_with_index sử dụng hai biến và đặt phần tử vào một trong các biến và chỉ mục trong phần tử kia.

here is a good description of how blocks and iterators work

2

luận Khối làm theo tất cả các quy ước tương tự như thông số phương pháp (ít nhất là 1,9): bạn có thể xác định đối số tùy chọn, danh sách arg chiều dài thay đổi, giá trị mặc định, vv Đây là một pretty decent summary. Một số điều cần lưu ý: bởi vì các khối nhìn thấy các biến trong phạm vi chúng được định nghĩa, nếu bạn chuyển vào một đối số có cùng tên với biến hiện tại, nó sẽ "ẩn" nó - khối của bạn sẽ thấy được chuyển thành giá trị và biến ban đầu sẽ không thay đổi.

i = 10 
25.times { | i | puts i } 
puts i #=> prints '10' 

Sẽ in '10' ở cuối. Bởi vì đôi khi đây là hành vi mong muốn ngay cả khi bạn không chuyển một giá trị (nghĩa là bạn muốn chắc chắn rằng bạn không vô tình che dấu một biến từ phạm vi xung quanh), bạn có thể chỉ định các tên biến khối cục bộ sau dấu chấm phẩy sau danh sách đối số:

x = 'foo' 
25.times { | i ; x | puts i; x = 'bar' } 
puts x #=> prints 'foo' 

ở đây, 'x' là địa phương để các khối, mặc dù không có giá trị được truyền vào.

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