2011-07-30 15 views
5

Chciałbym móc uzyskać w ramach przeliczalnego bloku, w celu utworzenia kodu benchmarkingowego zestawu znaków.Ruby: Wydajność w ramach przeliczania

Zasadniczo chciałbym coś zrobić to (uproszczony):

def iterator(enumerable, &block) 
    iterations = enumerable.size 
    counter = 0 
    enumerable.each do |item| 
    counter +=1 
    puts "Iterating #{counter}/#{iterations}..." 
    yield 
    end 
end 

Następnie chciałbym, aby móc korzystać z tej metody, aby owinąć ten kod boilerplate benchmarkingu wokół bloku Byłbym iteracji, tak że mogę nazwać coś takiego:

# assuming foo is an enumerable collection of objects 
iterator foo do 
    item.slow_method 
    item.mundane_method 
    item.save 
end 

... a gdy ten kod wykonywany chciałbym uzyskać następujące dane wyjściowe dziennika:

Iterating 1/1234... 
Iterating 2/1234... 
Iterating 3/1234... 

Wygląda na to, że tego rodzaju rzeczy muszą być możliwe, ale nie byłem w stanie określić składni ani tego, jak to się nazywa (żeby to sprawdzić).

Problem polega na tym, że muszę owinąć płytę standardową zarówno na zewnątrz obiektu przeliczalnego, który ma przejść do iteracji, jak i wewnątrz bloku iteracyjnego. Mogę przepuścić obiekt przeliczalny, ale nie mogę wywoływać metod na iterowanych obiektach wewnątrz bloku, przez który przechodzę.

Mam nadzieję, że to wyjaśnienie ma sens, trudno mi opisać to. Proszę zostawić komentarz, jeśli potrzebujesz wyjaśnienia czegokolwiek, postaram się wyjaśnić lepiej.

+0

może chcesz użyć 'enumerable.zip (1..size) .each do | artykuł, licznik | 'dla" czystszego "wyglądającego kodu. –

Odpowiedz

7

Instrukcja Ruby za yield może przyjmować argumenty. Użytkownik chce powiedzieć:

yield item 

Przekazuje element "bieżący" do bloku "na zewnątrz".

Mam nadzieję, że poprawnie zrozumiałem pytanie.

DODATEK

A oto kod, aby zobaczyć go w akcji:

class Item 
    def initialize(id) 
    @id = id 
    end 
    def slow_method() 
    puts "slow #@id" 
    end 
    def mundane_method() 
    puts "mundane #@id" 
    end 
    def save() 
    puts "save #@id" 
    end 
end 

foo = [Item.new(100), Item.new(200), Item.new(300)] 

def iterator(enumerable, &block) 
    iterations = enumerable.size 
    counter = 0 
    enumerable.each do |item| 
    counter +=1 
    puts "Iterating #{counter}/#{iterations}..." 
    yield item 
    end 
end 

iterator foo do |item| 
    item.slow_method 
    item.mundane_method 
    item.save 
end 
+0

To naprawiło to, dokładnie to musiałem wiedzieć. Dziękuję Ci! – Andrew