Rozdział ten odkrywa więcej struktur sterujących Rubiego.
case
Używamy instrukcji case
do przetestowania sekwencji warunków. To pozornie podobna instrukcja do switch
'a z C i Javy, ale jest znacznie bardziej potężny, tak jak to powinniśmy zobaczyć poniżej.
ruby> i=8
ruby> case i
| when 1, 2..5
| puts "1..5"
| when 6..10
| puts "6..10"
| end
6..10
nil
2..5 jest wyrażeniem oznaczającym przedział od 2 do 5 włącznie. Poniższe wyrażenie sprawdza czy wartość i
należy do tego przedziału:
(2..5) === i
case
wewnętrznie używa operatora relacji ===
by sprawdzić kilkanaście warunków za jednym razem. Zgodnie z obiektową naturą Rubiego, ===
jest interpretowany odpowiednio dla obiektu, który ukazał się w warunku. Na przykład, następujący kod sprawdza w pierwszym przypadku równość łańcuchów znakowych, kiedy w drugim przypadku sprawdza dopasowanie do wyrażeń regularnych.
ruby> case 'abcdef'
| when 'aaa', 'bbb'
| puts "aaa lub bbb"
| when /def/
| puts "includes /def/"
| end
includes /def/
nil
while
Ruby dostarcza wygodne sposoby do tworzenia pętli, chociaż można znaleźć w następnym rozdziale, że uczenie się, jak używać iteratorów będzie bardzo często zbędne do pisania wyraźnych pętli.
while
jest powtarzanym if
'em. Użyliśmy go w naszej zgadywance i w programach z wyrażeniami regularnymi (patrz poprzedni rozdział); tam, to przyjmuje formę while warunek ... end
otaczającą blok powtarzanego kodu dopóki warunek jest prawdą. Ale while
i if
, mogą z łatwością być stosowane jako indywidualne instrukcje:
ruby> i = 0
0
ruby> puts "To jest zero." if i==0
To jest zero.
nil
ruby> puts "To liczba ujemna." if i<0
nil
ruby> puts i+=1 while i<3
1
2
3
nil
Czasami będziesz chciał zanegować sprawdzany warunek. unless
jest zanegowanym if
'em i until
jest zanegowanym while
'm. Pozostawimy ją dla Ciebie do eksperymentowania na niej.
Istnieją cztery możliwości przerwania przebiegu pętli od wewnątrz. Pierwsza, break
, znaczy to samo co w C, aby uciec z pętli całkowicie. Druga, next
przeskakująca do początku następnej iteracji tej pętli (zgodna do continue
z języka C). Trzecia, rubiego redo
, która oznacza ponowne wykonanie bieżącej iteracji. Następujący kod w języku C ilustruje znaczenia instrukcji break
, next
i redo
:
while(warunek) {
label_redo:
goto label_next; /* ruby's "next" */
goto label_break; /* ruby's "break" */
goto label_redo; /* ruby's "redo" */
...
...
label_next:
}
label_break:
...
Czwartym sposobem by wyjść z wnętrza pętli jest return
. Dokonanie oceny return
'a powoduje wyjście nie tylko z pętli lecz także z metody, która zawiera pętlę. Jeżeli podany został argument, będzie on zwrócony z wywołania metody, w przeciwnym wypadku zwrócony będzie nil
.
for
Programiści C będą się teraz zastanawiać, jak zrobić pętlę "for". For
w Ruby może służyć temu samemu celowi, ale dodaje pewną elastyczność. Poniższa pętla działa raz dla każdego elementu zbioru (array, hash, sekwencji numerycznej, itd.), ale sprawia że programista nie myśli o indeksach:
for elt in collection
# ... tutaj, elt odnosi się do elementu z kolekcji
end
Zbiór może być zakresem wartości (tym o czym większość ludzi myśli, kiedy mówimy o pętli for):
ruby> for num in (4..6)
| puts num
| end
4
5
6
4..6
W tym przykładzie przechodzimy przez niektóre elementy tablicy:
ruby> for elt in [100,-9.6,"pickle"]
| puts "#{elt}\t(#{elt.class})"
| end
100 (Fixnum)
-9.6 (Float)
pickle (String)
[100, -9.6, "pickle"]
Jesteśmy coraz dalej. for
wraz z each
jest naprawdę innym sposobem wypisywania każdego elementu, który tak się składa, jest naszym pierwszym przykładem iteratora. Poniższe dwie formy są równoważne:
# Jeśli używałeś C lub Javy, możesz woleć ten.
for element in collection
...
end
# Programiści Smalltalk'a mogą woleć ten.
collection.each {|element|
...
}
Iteratory często mogą być zastępowane zwykłymi pętlami i po przyzwyczajeniu się do nich, są na ogół łatwiejsze do zaaplikowania. Więc przejdźmy dalej i nauczmy się o nich więcej.