2010-03-23 34 views

Trả lời

43

Từ khóa yield của Ruby là một thứ rất khác với từ khóa Python có cùng tên, do đó đừng nhầm lẫn với từ khóa đó. Từ khóa yield của Ruby là cú pháp đường để gọi một khối liên kết với một phương thức.

Điểm tương đương gần nhất là lớp Enumerator của Ruby. Ví dụ, tương đương với Python:

def eternal_sequence(): 
    i = 0 
    while True: 
    yield i 
    i += 1 

là thế này:

def eternal_sequence 
    Enumerator.new do |enum| 
    i = 0 
    while true 
     enum.yield i # <- Notice that this is the yield method of the enumerator, not the yield keyword 
     i +=1 
    end 
    end 
end 

Bạn cũng có thể tạo điều tra viên cho các phương pháp liệt kê hiện có với enum_for. Ví dụ: ('a'..'z').enum_for(:each_with_index) cung cấp cho bạn một điều tra các chữ thường cùng với vị trí của chúng trong bảng chữ cái. Bạn nhận được điều này miễn phí với các phương pháp Enumerable tiêu chuẩn như each_with_index trong 1.9, vì vậy bạn chỉ có thể viết ('a'..'z').each_with_index để có được điều tra viên.

+2

'0.step' là một liệt kê vĩnh cửu kể từ 1.9 – steenslag

21

Tôi đã nhìn thấy Fibers sử dụng theo cách đó, hãy xem xét một ví dụ từ this article:

fib = Fiber.new do 
    x, y = 0, 1 
    loop do 
    Fiber.yield y 
    x,y = y,x+y 
    end 
end 
20.times { puts fib.resume } 
+6

Thực tế, trong phần tử' Enumerator' được thực hiện bằng cách sử dụng 'Fiber'. Đó là một trong những lý do chính để thêm chúng vào thực tế, bởi vì trong Ruby 1.8 'Enumerator' s sử dụng sự tiếp tục, nhưng đó là a) khá khó sử dụng và b) tại thời điểm đó, các phần tiếp theo sẽ bị loại bỏ khỏi ngôn ngữ Ruby. –

10

Nếu bạn đang tìm kiếm để lười biếng tạo ra giá trị, @ câu trả lời của Chuck là điều đúng.

Nếu bạn đang tìm cách lười biếng lặp lại trên một bộ sưu tập, Ruby 2.0 đã giới thiệu bộ đếm số .lazy mới.

range = 1..Float::INFINITY 
puts range.map { |x| x+1 }.first(10) # infinite loop 
puts range.lazy.map { |x| x+1 }.first(10) # [2, 3, 4, 5, 6, 7, 8, 9, 10, 11] 
Các vấn đề liên quan