Z lekcji 5 wiesz już, że funkcja jest kodem wielokrotnego użytku, który dostarcza instrukcji do wykonania akcji lub do utworzenia danych wyjściowych na podstawie danych wejściowych.
Aby zdefiniować funkcję, trzeba podać trzy kluczowe części: unikatowy identyfikator, typ informacji, jakiej można oczekiwać w wyniku, a także to, co funkcja będzie robić po jej wywołaniu.
Definiowanie funkcji
Sygnatury funkcji
W lekcji 3 powiedzieliśmy sobie, jak zadeklarować zmienną lub stałą poprzez nadanie jej nazwy i podanie typu wartości, której będzie używać.
Sygnatura funkcji działa na podobnej zasadzie. Sygnatura funkcji wykorzystuje unikatowy identyfikator funkcji wraz z parametrami, które opisują potrzebne dane wejściowe, a także typ zwracany dla wyniku lub danych wyjściowych.
To, co funkcja rzeczywiście robi, jest zdefiniowane w bloku kodu.
Blok kodu
Blok kodu to grupa wyrażeń, która znajduje się po sygnaturze funkcji. Oto składnia funkcji i jej bloku kodu:
name() : type =
codeblock
Istnieje kilka sposobów formatowania bloku kodu. Jednym z nich jest wcięcie wierszy kodu po identyfikatorze. Widać to w powyższej składni funkcji. (Później dowiesz się więcej o tym, jak skonfigurować bloki kodu, a na razie możesz skorzystać z tej opcji).
Wyrażenia w bloku kodu definiują, co ta funkcja rzeczywiście zrobi, gdy zostanie wywołana.
Wyrażenia te zostaną uruchomione tylko wtedy, gdy ta funkcja zostanie wywołana. Gdy program osiągnie koniec tego bloku kodu, wyrażenia te zostaną zakończone – przynajmniej do następnego wywołania tej funkcji – a program wykona następny fragment kodu, który nastąpi po tym wywołaniu funkcji.
Ciało
Blok kodu jest również nazywany ciałem, gdy definiuje działanie funkcji.
Zakres
Jak na razie wiesz już, że:
- Funkcja ma unikatowy identyfikator, który jest używany do aktywowania jej w celu wykonania jakiejś czynności w programie.
- To, co robi funkcja, opiera się na wyrażeniach w jej ciele.
- Po wykonaniu ostatniego wiersza kodu w treści wywołanie funkcji zostaje zakończone, a program przechodzi do następnego wiersza kodu po wywołaniu funkcji, który znajduje się w programie.
Instrukcje w tej funkcji i wszelkie wartości, które pochodzą z funkcji, określają zakres funkcji.
Wróćmy do wyrażeń, których możesz użyć do zdefiniowania funkcji. Możesz utworzyć stałe i zmienne (to z lekcji 3, pamiętasz?) i dodać je do ciała funkcji.
Gdy umieścisz zmienną w ciele, będzie ona lokalna dla zakresu funkcji. Lokalna w tym sensie oznacza, że ten kod funkcjonuje i działa tylko w tym ciele i tylko wtedy, gdy funkcja jest wywoływana.
Czym jest więc zakres? Jest to powiązanie nazwy funkcji z wartością generowaną przez funkcję. Wartości tej można użyć tylko w bloku kodu, w którym została utworzona – lub w tym zakresie.
Tworzenie instancji
Instancja jest unikatowym zastosowaniem danej funkcji w momencie jej wywołania i wykonania. Tworzenie instancji bywa nazywane instancjonowaniem. Zwróć uwagę, że zarówno instancja (instance) jak i instancjonowanie (instantiation) są powiązane ze słowem instant, które z angielskiego oznacza bardzo krótki czas.
To z kolei prowadzi do pojęcia czasu życia.
Czas życia
Instancja ma określony czas życia – początek, środek i koniec.
Oznacza to, że czas życia tego, co znajduje się w tym ciele funkcji, jest ograniczony do zakresu tego ciała i nie można uzyskać dostępu do zmiennych lokalnych (tych ograniczonych do bieżącego zakresu) poza zakresem.
Wyrażenia warunkowe
Poniższy przykład ilustruje sposób obliczania maksymalnej liczby pułapek na myszy, jaką gracz może zakupić za posiadaną liczbę monet.
Stała MousetrapsYouCanBuy została utworzona w bloku if, zatem zakres jest ograniczony do bloku if.
Gdy stała MaxMousetrapsYouCanBuy zostanie wykorzystana poza blokiem kodu if, wygeneruje błąd, ponieważ nazwa MaxMousetrapsYouCanBuy nie istnieje poza zakresem. Zobaczysz komunikat o błędzie: Nieznany identyfikator. Oznacza to, że stała MaxMousetrapsYouCanBuy jest poprawna tylko w tym zakresie.
Gdy wyrażenie zostanie zakończone, stałe lokalne i zmienne lokalne utworzone w ciele przestaną istnieć. Osiągnęły one koniec swojego życia.
Potraktuj zakres jako mały fragment kodu, w którym wszystko działa, dopóki nie zostanie ukończone.
Składnia funkcji
Przyjrzyjmy się ponownie składni funkcji, ale tym razem nieco dokładniej.
name() : type =
codeblock
name() : type = |
To jest sygnatura funkcji. Jest to Sygnatura funkcji zawiera typ danych wejściowych, które zostaną użyte. Wartość zwracana przez funkcję (to, co znajduje się po znaku |
codeblock |
Blok kodu funkcji lub ciało to miejsce, w którym dodajesz stałe, zmienne lub inne wyrażenia, aby pokazać, co funkcja zrobi po wywołaniu. |
Na przykład funkcja zapłaty za pułapkę na myszy może wyglądać następująco:
var Coins : int = 500
CoinsPerMousetrap : int = 100
BuyMousetrap() : void =
set Coins = Coins - CoinsPerMousetrap
Print("Pułapka na myszy została kupiona! Pozostało ci monet: {Coins}.")
Konwencje i zasady nazewnictwa dotyczące nazw funkcji są takie same, jak w przypadku zmiennych i stałych. Funkcje wykonują sekwencję działań, więc dobrą praktyką jest nazywanie ich w sposób, który odzwierciedla działania, jakie wykonują, na przykład BuyMousetrap().
Pusty typ danych (void)
Być może twoją uwagę zwrócił typ void w sygnaturze funkcji BuyMousetrap(). Typ void funkcji oznacza, że wywołanie funkcji nie zwróci żadnej wartości. Więcej o typie 'void' i jego zastosowaniu dowiesz się w następnej lekcji.
Nie powtarzaj się
Ważną zasadą programowania jest, żeby się nie powtarzać.
Oznacza to, że jeśli powtarzasz wiersz kodu co najmniej trzy razy, warto rozważyć napisanie go w inny sposób. Tak, jest ku temu powód!
Im więcej wierszy kodu piszesz, tym trudniej jest go utrzymać i tym bardziej prawdopodobne jest, że wystąpią błędy, gdy zmienisz kod w jednym miejscu, ale nie w innym – a na pewno do tego dojdzie.
Funkcje, podobnie jak stałe, pozwalają uniknąć powtarzania kodu, gdy nie jest to konieczne, więc dzięki nim nie tylko nie powielasz kodu, ale także ograniczasz konieczność jego utrzymania i zmniejszasz prawdopodobieństwo wystąpienia błędów w kodzie.
Podczas pisania kodu zwracaj uwagę na wielkość liter, zarówno w nazwach wyrażeń i funkcji, jak i podczas używania słów kluczowych i wbudowanych funkcji. Wielkość liter w Verse ma znaczenie, a błędy w poprawnej i spójnej pisowni mogą prowadzić do bugów i błędów kompilacji.
Podsumowanie
- Funkcja jest kodem wielokrotnego użytku, który dostarcza instrukcji dotyczących wykonania akcji lub utworzenia wyniku wyjściowego na podstawie danych wejściowych.
- Funkcje składają się z trzech elementów: identyfikatora, typu i bloku kodu, który zawiera wynik, jaki funkcja generuje po wywołaniu.
- Funkcje są wywoływane przez ich sygnatury funkcji.
- Blok kodu jest również nazywany ciałem, gdy definiuje działanie funkcji.
- Zakres odnosi się do wartości powiązanej z funkcją, która z kolei jest definiowana przez zawartość bloku kodu.
- Kod zawarty w bloku kodu jest lokalny dla tego zakresu.
- Czas życia to okres trwania zakresu.
- Nie powtarzaj się.