Pętla foreach, pętla „po kolekcji” – w programowaniu rodzaj pętli, której wykonanie polega na powtarzaniu kolejnych iteracji dla wszystkich elementów (komórek) wybranego agregatu danych, takiego jak, np. tablica, lista, kolekcja, kolejka lub innego, dostępnego w danym języku programowania, bądź jego konkretnej implementacji. Pętla taka automatycznie przed przejściem do wykonania kolejnej iteracji przypisuje zadanej w nagłówku pętli zmiennej sterującej wartość kolejnego elementu (komórki).
Składnia zapisu tego rodzaju pętli jest różna w poszczególnych językach programowania, lecz można wyodrębnić pewne ogólne, charakterystyczne zasady:
for each
(np. Visual Basic[1], VBA[2]), lub pisane łącznie jedno słowo foreach
(np. D[3], PHP[4]); rzadziej słowo for
i słowo foreach
stanowią synonim i mogą być używane zamiennie, zarówno w pętli ogólnej, jak i w pętli "po kolekcji" (np. Perl[5]), lub innein
do
.Natomiast składnia tej pętli, w tych językach, w których występuje pętla ogólna, często wzorowana jest na składni tej pętli. W tym przypadku zamiast słów łączących stosuje się nawiasy i średniki.
Działanie tej pętli polega na wykonaniu następujących kroków:
Pętla tego typu dostępna jest w nowszych językach, w szczególności w językach zorientowanych na programowanie obiektowe, w których zrealizowano dynamiczne struktury danych. Również w kolejnych implementacjach języków, w których nie było tego rodzaju pętli, wprowadza się ją, szczególnie wraz z wprowadzaniem nowych kontenerów danych dostępnych standardowo w nowych implementacjach.
język programowania | składnia |
---|---|
Ada[6][7] |
for zmienna-sterująca in [reverse] kontener-typ-lub-zakres [range zakres] loop
-- instrukcje
end loop;
|
D[3] |
foreach(zmienna-sterująca; kontener) /* instrukcja */;
|
JavaScript[8][9] |
for (zmienna-sterująca in kontener) /* instrukcja */;
|
Lua[10] | for indeks, zmienna-sterująca in pairs(kontener) do
-- instrukcje
end
|
Perl[5] |
foreach zmienna-sterująca (kontener) {
# instrukcje
}
for zmienna-sterująca (kontener) {
# instrukcje
}
|
PHP[4] |
foreach(kontener as zmienna-sterująca) {
/* instrukcje */ }
|
Python[11] |
for zmienna-sterująca in kontener:
# instrukcje
|
Visual Basic[1], VBA[2] |
For Each zmienna-sterująca In kontener
' instrukcje
Next zmienna-sterująca
|
Uwaga: nawiasy kwadratowe obejmują frazy opcjonalne |
Pętlę foreach można zaimplementować za pomocą innych konstrukcji dostępnych w danym języku programowania. Pętla ta została wprowadzona do języków programowania lub ich kolejnych, nowszych implementacji jako rozwinięcie wcześniej stosowanych pętli, jako konstrukcja działająca na wyższym poziomie abstrakcji, która czytelniej dla programisty oddaje sens wykonywanych operacji oraz uwalnia go od konieczności jawnego kodowania mało istotnych szczegółów realizacyjnych. Zapis tej pętli jest zapisem samo dokumentującego się kodu źródłowego programu.
Za pomocą instrukcji warunkowej i skoku można zrealizować każdą pętlę, także pętlę "po kolekcji". Widoczna jest jednak nieczytelność takiego kodu w porównaniu do pętli foreach, realizującej zadanie na znacznie wyższym poziomie abstrakcji.
Visual Basic[1], VBA[2] | |
---|---|
foreach | if, goto |
For Each I In Kontener
' instrukcje
Next I
|
Ix=1
LenK=Kontener.Len
start: If Ix>LenK then Goto koniec
I=Kontener.Item(Ix)
' instrukcje
Ix=Ix+1
Goto start
koniec:
|
Pętla repetycyjna w porównaniu z instrukcją warunkową i skoku pozwana nieco czytelniej zrealizować zadnie pętli foreach, lecz nadal trzeba kodować wiele dodatkowych czynności, realizowanych w pętli "po kolekcji" niejawnie.
Visual Basic[1], VBA[2] | |
---|---|
foreach | repetycyjna |
For Each I In Kontener
' instrukcje
Next I
|
Ix=1
LenK=Kontener.Len
Do While Ix<=LenK
I=Kontener.Item(Ix)
' instrukcje
Ix=Ix+1
Loop
|
Realizacja pętli foreach za pomocą pętli iteracyjnej jest łatwa i przejrzysta, pod warunkiem, że istnieje mechanizm badania liczby elementów kontenera danych, niezbędny od ustalenia liczby powtórzeń, lub badania wartości granicznych (granicy dolnej i górnej) indeksów elementów kontenera danych. Szczególną analogię można dostrzec pomiędzy instrukcją foreach a instrukcją iteracyjnych w tych językach programowania, w których instrukcja iteracyjna ma składnię taką jak foreach, tzn. w których określamy, że zmienna sterująca ma przyjmować kolejne wartości podanego zakresu, tak jak to ma miejsce np. w języku Ada[6][7] (for i in w1..w2 loop ... end loop;
). Pętla ta ma możliwość zresztą wykonywania iteracji np. dla wszystkich wartość określonego typu danych lub dla wszystkich komórek tablicy: for i in typ_danych-lub-tablica loop ... end loop;
, także dla zakresu: for i in typ_danych range w1..w2 loop ... end loop;
, for i in tablica'range(x) loop ... end loop;
, oraz w odwrotnej kolejności (modyfikator reverse
): for i in reverse typ_danych-lub-tablica loop ... end loop;
; co w dużym stopniu klasyfikuje tę pętlę jako pętlę zarówno iteracyjną jak i przede wszystkim "po kolekcji"[6][7].
Visual Basic[1], VBA[2] | Ada[6][7] | ||
---|---|---|---|
foreach | iteracyjna | foreach | iteracyjna |
For Each I In Kontener
' instrukcje
Next I
|
LenK=Kontener.Len
For Ix=1 To LenK
I=Kontener.Item(Ix)
' instrukcje
Next Ix
|
for I in Kontener loop
-- instrukcje
end loop
|
ws:=Kontener'First
wp:=Kontener'Last
for Ix in ws..wp loop
I=Kontener(Ix)
-- instrukcje
end loop
|
Również pętla ogólna umożliwia implementację pętli foreach na zasadach takich jak dla pętli iteracyjnej (iterowanie po kolejnych indeksach kontenera danych), i repetycyjnej (jawny zapis warunku pętli).
D[3] | |
---|---|
foreach | ogólna |
foreach(I; Kontener)
{
/* instrukcje */
}
|
for(Ix=0; Ix<Kontener.length; Ix++)
{
I=Kontener[Ix];
/* instrukcje */
}
|
for
dla pętli "po kolekcji" lecz słowo foreach
, a słowo for
zaleca się stosować dla pętli ogólnej.