Właśnie miałem szybkie pytanie dotyczące pętli w Ruby. Czy istnieje różnica między tymi dwoma sposobami iteracji w kolekcji?
# way 1
@collection.each do |item|
# do whatever
end
# way 2
for item in @collection
# do whatever
end
Zastanawiam się tylko, czy są dokładnie takie same, czy może istnieje subtelna różnica (być może, gdy @collection
zero).
x
pozostaje scenariusz for , jest fakt, że (ogólnie rzecz biorąc) słowa kluczowe nie tworzą nowych zakresów. jeśli , chyba , zacząć , za , natomiast itp wszelkich prac z bieżącego zakresu.#each
akceptuje jednak blok. Bloki zawsze dodają własny zakres na bieżącym zakresie. Oznacza to, że zadeklarowanie nowej zmiennej w bloku (a więc nowego zakresu) nie będzie dostępne spoza bloku, ponieważ ten dodatkowy zakres nie jest tam dostępny.Dobre wyjaśnienie znajduje się w „ The Evils of the Loop ” (istnieje jedna niewielka różnica w zakresie określania zakresu zmiennych).
Używanie
each
jest uważane za bardziej idiomatyczne użycie Ruby.źródło
Twój pierwszy przykład
jest bardziej idiomatyczny . Podczas gdy Ruby obsługuje konstrukcje zapętlające się jak
for
iwhile
, ogólnie preferowana jest składnia bloku.Inną subtelną różnicą jest to, że dowolna zmienna zadeklarowana w
for
pętli będzie dostępna poza pętlą, podczas gdy te w bloku iteratora są faktycznie prywatne.źródło
while
iuntil
faktycznie mają bardzo konkretne zastosowania, których nie można zastąpić każdym z nich, na przykład generowanie unikalnych wartości lub REPL.Jeszcze jeden inny ...
źródło: http://paulphilippov.com/articles/enumerable-each-vs-for-loops-in-ruby
dla lepszego wyjaśnienia: http://www.ruby-forum.com/topic/179264#784884
źródło
Wygląda na to, że nie ma różnicy,
for
używaeach
pod spodem.Jak mówi Bayard, każdy jest bardziej idiomatyczny. Ukrywa przed tobą więcej i nie wymaga specjalnych funkcji językowych. Komentarz Per Telemachusa
for .. in ..
ustawia iterator poza zakresem pętli, więcliście
a
zdefiniowane po zakończeniu pętli. Gdzieeach
nie. To kolejny powód do używaniaeach
, ponieważ zmienna temp żyje krócej.źródło
for
nie używa sięeach
pod spodem. Zobacz inne odpowiedzi.Nigdy nie używaj
for
go, może powodować prawie niewykrywalne błędy.Nie daj się zwieść, nie chodzi o idiomatyczny kod lub problemy ze stylem. Implementacja Ruby
for
ma poważną wadę i nie powinna być używana.Oto przykład, w którym
for
wprowadza błąd,Wydruki
Korzystanie z
%w{foo bar quz}.each { |n| ... }
wydrukówCzemu?
W
for
pętli zmiennan
jest definiowana tylko raz, a następnie dla wszystkich iteracji używana jest jedna definicja. Stąd każdy blok odnosi się do tego samego,n
który ma wartośćquz
do czasu zakończenia pętli. Pluskwa!W
each
pętli świeża zmiennan
jest definiowana dla każdej iteracji, na przykład powyżej zmiennejn
jest definiowana trzy osobno. Dlatego każdy blok odnosi się do osobnegon
z poprawnymi wartościami.źródło
O ile mi wiadomo, stosowanie bloków zamiast struktur kontrolnych w języku jest bardziej idiomatyczne.
źródło
Chcę tylko zwrócić uwagę na pętlę for in w Ruby. Może wydawać się konstrukcją podobną do innych języków, ale w rzeczywistości jest to wyrażenie jak każda inna konstrukcja pętli w Rubim. W rzeczywistości for in działa z obiektami policzalnymi tak jak każdy iterator.
Kolekcja przekazywana do w może być dowolnym obiektem, który ma metodę każdego iteratora. Tablice i skróty definiują każdą metodę, podobnie jak wiele innych obiektów Ruby. Pętla for / in wywołuje każdą metodę określonego obiektu. Ponieważ iterator zwraca wartości, pętla for przypisuje każdą wartość (lub każdy zestaw wartości) do określonej zmiennej (lub zmiennych), a następnie wykonuje kod w treści.
To głupi przykład, ale ilustruje to, że pętla for in działa z KAŻDYM obiektem, który ma każdą metodę, podobnie jak robi to każdy iterator:
A teraz każdy iterator:
Jak widać, oba reagują na każdą metodę, która zwraca wartości z powrotem do bloku. Jak wszyscy tutaj stwierdzili, zdecydowanie lepiej jest używać każdego iteratora niż w pętli for. Chciałem po prostu jechać do domu do tego stopnia, że w pętli for in nie ma nic magicznego. Jest to wyrażenie, które wywołuje każdą metodę kolekcji, a następnie przekazuje ją do swojego bloku kodu. W związku z tym jest to bardzo rzadki przypadek, w którym należałoby użyć w. Używaj każdego iteratora prawie zawsze (z dodatkową zaletą zakresu bloków).
źródło
W pętli „for” zmienna lokalna nadal żyje po każdej pętli. W pętli „każda” zmienna lokalna odświeża się po każdej pętli.
źródło