Enumerable#lazy
polega na przeliczaniu podając metodę #each
. Jeśli Twój przeliczalny nie ma metody #each
, nie możesz użyć #lazy
. Teraz Kernel#enum_for
i #to_enum
zapewniają elastyczność, aby określić metodę wyliczenia innego niż #each
:Jaki jest najlepszy sposób na zwrócenie Enumerator :: Lazy, gdy klasa nie definiuje #each?
Kernel#enum_for(method = :each, *args)
Ale #enum_for
i przyjaciele zawsze skonstruować zwykły (nie-leniwych) rachmistrzów, nigdy Enumerator::Lazy
.
widzę, że Enumerator
w Ruby 1.9.3 oferuje ten podobną formę #Nowe:
Enumerator#new(obj, method = :each, *args)
Niestety że konstruktor został całkowicie usunięty w Ruby 2.0. Również nie sądzę, że był kiedykolwiek dostępny na Enumerator::Lazy
. Tak więc wydaje mi się, że jeśli mam klasę z metodą, chcę zwrócić leniwy moduł wyliczający dla, jeśli ta klasa nie ma #each
, wtedy muszę zdefiniować jakąś klasę pomocniczą, która definiuje #each
. Na przykład mam klasę Calendar
. To naprawdę nie ma sensu oferować wymieniania każdej daty od początku wszechczasów. Numer #each
byłby bezużyteczny. Zamiast tego oferuje metodę, która wylicza (leniwie) od daty rozpoczęcia:
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
I EachFrom
klasy wygląda następująco:
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
To działa, ale czuje się ciężki. Może powinienem podklasować Enumerator::Lazy
i zdefiniować konstruktora takiego, który jest przestarzały z Enumerator
. Co myślisz?
Po prostu rozwaliłaś mój umysł, Marc-André. Mój kod właśnie przeszedł od idiotycznego do idiomatycznego. Nie rozumiałem, że Ruby chce, abyśmy zawsze kręcili w Enumeratorach, a nie Enumerator :: Lazy. Gdziekolwiek potrzebujemy czegoś, aby być leniwym, prosimy o wyliczenie dla wersji #lazy. Minusem może być to, że użytkownicy naszych abstrakcji naprawdę muszą wiedzieć, kiedy zadzwonić #lazy (np. Przed wywołaniem #drop (n)). Plusem jest czysty kod. –
Miałem wiele problemów (i wiele się nauczyłem) #drop (n). Teraz, gdy zwracam "zwykłych" enumeratorów wszędzie musiałem posypać kilka ... lazy.drop (n) ... o. Tak więc zdefiniowałem metodę podobną do kropli, która po prostu przyspiesza działanie modułu wyliczającego, pozwalając mi zmienić te wartości na ... pomiń (n) ... –
Dobrze. Zdecydowanie można zdefiniować taką metodę, jak 'Enumerable # skip (n)', która zwróci 'Enumerator' zamiast tablicy jak' drop' i zagra z tą. –