Tôi mới sử dụng Ruby, có cách nào để các giá trị yield
từ các chức năng của Ruby không? Nếu có, làm thế nào? Nếu không, lựa chọn của tôi để viết mã lười là gì?Có cái gì đó giống như máy phát điện Python trong Ruby?
Trả lời
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.
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 }
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. –
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]
'0.step' là một liệt kê vĩnh cửu kể từ 1.9 – steenslag