Enumerable#lazy
dựa vào số bạn cung cấp phương thức #each
. Nếu số đếm của bạn không có phương thức #each
, bạn không thể sử dụng #lazy
. Bây giờ Kernel#enum_for
và #to_enum
cung cấp sự linh hoạt để xác định một phương pháp liệt kê khác hơn #each
:Cách tốt nhất để trả lại một điều tra viên là gì? Lười biếng khi lớp học của bạn không định nghĩa #each?
Kernel#enum_for(method = :each, *args)
Nhưng #enum_for
và bạn bè luôn luôn xây dựng đơn giản (không lười biếng) điều tra viên, không bao giờ Enumerator::Lazy
.
Tôi thấy rằng Enumerator
trong Ruby 1.9.3 cung cấp hình thức tương tự như này # mới:
Enumerator#new(obj, method = :each, *args)
Đáng tiếc là nhà xây dựng đã được loại bỏ hoàn toàn trong Ruby 2.0. Ngoài ra tôi không nghĩ rằng nó đã có sẵn ở tất cả trên Enumerator::Lazy
. Vì vậy, có vẻ như với tôi rằng nếu tôi có một lớp học với một phương pháp tôi muốn trả lại một điều tra lười biếng cho, nếu lớp đó không có #each
thì tôi phải xác định một số lớp trợ giúp mà xác định #each
.
Ví dụ: tôi có lớp học Calendar
. Nó không thực sự có ý nghĩa đối với tôi để cung cấp để liệt kê mọi ngày từ đầu mọi thời đại. An #each
sẽ là vô dụng. Thay vào đó tôi đưa ra một phương pháp mà liệt kê (uể oải) từ ngày bắt đầu:
class Calendar
...
def each_from(first)
if block_given?
loop do
yield first if include?(first)
first += step
end
else
EachFrom.new(self, first).lazy
end
end
end
Và đó lớp EachFrom
trông như thế này:
class EachFrom
include Enumerable
def initialize(cal, first)
@cal = cal
@first = first
end
def each
@cal.each_from(@first) do |yielder, *vals|
yield yielder, *vals
end
end
end
Nó hoạt động nhưng nó cảm thấy nặng nề. Có lẽ tôi nên phân lớp Enumerator::Lazy
và xác định một hàm tạo như thế không được dùng nữa từ Enumerator
. Bạn nghĩ sao?
Bạn vừa mới thổi tâm trí của tôi là Marc-André. Mã của tôi chỉ từ idiotic đến thành ngữ. Tôi không hiểu rằng Ruby muốn chúng tôi luôn luôn lưu lượng truy cập trong Enumerators và không Enumerator :: Lazy. Bất cứ nơi nào chúng ta cần một cái gì đó để được lười biếng, chúng tôi yêu cầu điều tra cho phiên bản #lazy. Nhược điểm có lẽ là người dùng trừu tượng của chúng tôi thực sự phải hiểu khi nào nên gọi #lazy (ví dụ: trước khi gọi #drop (n)). Phía trên là mã sạch. –
Tôi đã gặp rất nhiều rắc rối với (và học được rất nhiều từ) #drop (n). Bây giờ tôi đang trở lại "đồng bằng" Enumerators ở khắp mọi nơi tôi đã phải rắc một vài ... lazy.drop (n) ... về. Vì vậy, tôi đã định nghĩa một phương thức giống như drop-up đơn giản là tiến lên Enumerator, cho phép tôi thay đổi chúng thành ... skip (n) ... –
Right. Bạn chắc chắn có thể định nghĩa một phương thức như 'Enumerable # skip (n)' sẽ trả về một 'Enumerator' thay vì một mảng như' drop' làm và chơi với nó. –