Czytany Wpis

Absolutne podstawy Lua. Funkcje

W dzisiejszym wpisie poświęconym absolutnym podstawom Lua zajmiemy się funkcje

Absolutne podstawy Lua. Funkcje

Dzisiejsza odsłona poświęcona zostanie funkcjom, czyli pewnym strukturom programistycznym, które niewątpliwie ułatwiają życie przy pisaniu kodu. Być może część z czytelników miała okazja zapoznać się z tym pojęciem na lekcjach matematyki, a jeśli tak faktycznie było, to takie pierwsze skojarzenie - o ile się pojawiło w głowie -  jest dość dobre, choć w wielu językach programowania funkcje nie muszą zawsze zwracać określonego wyniku (przynajmniej nie wprost) tak jak to miejsce w matematyce. Dlatego lepiej myśleć o funkcjach jako o pewnych jawnie wydzielonych fragmentach kodu, które odpowiadają za realizację ściśle określonego zadania, w momencie ich wywołania. To ostatnie stwierdzenie jest szalenie istotne, ponieważ utworzenie funkcji samo w sobie nie pociąga za sobą określonych efektów dla działania naszego programu, ponieważ funkcja sama w sobie opisuje pewien zestaw czynności do wykonania, coś w rodzaju przepisu na osiągnięcie pewnego efektu w określonych okolicznościach. Jednak ich praktyczną realizację możemy zaobserwować dopiero wówczas, kiedy w naszym skrypcie/aplikacji w sposób jawny postanowimy z niej skorzystać, czyli właśnie ją wywołamy. To tak jak z książką kucharską, która zawiera wiele przydatnych receptur na przepyszne dania, ale jeśli chcemy te wszystkie smakołyki poczuć w ustach, to ich pamięciowe opanowanie nie wystarczy, tylko musimy zakasać rękawy i udać się w kierunku kuchni.

Rzecz jasna można sobie znakomicie radzić bez korzystania z dobrodziejstwa funkcji (choć w niektórych językach jest to z definicji niemożliwe, ale Lua do nich akurat nie należy), ale niezaprzeczalne zalety jakie stoją za nimi czynią to raczej niepraktycznym dziwactwem (zwłaszcza w przypadku większych projektów czy aplikacji). Co więc zyskujemy dzięki temu rozwiązaniu:

Teraz czas na trochę wiedzy praktycznej. Zaczniemy od tego jak się funkcje powołuje do życia, czyli od sposobu ich deklaracji. Niżej przedstawiony został ogólny schemat:

local function nazwa_funkcji ( argument1, argument2, argument3,........

instrukcje do wykonania

return

end

Na początek mamy dwa słowa kluczowe local oraz function. Pierwsze z nich możemy kojarzyć z poprzedniej lekcji dotyczącej zmiennych i tutaj spełnia tę samą rolę, czyli określa zakres obowiązywania - w tym przypadku - funkcji. Tym samym słowo local nie jest w przypadku Lua obowiązkowe, ale twórcy Robloxa we własnym tutorialu każdorazowo nim się posługują, więc przyjmijmy tę konwencję. Później następuje słowo kluczowe function, które mówi o tym, że w tym miejscu zaczynamy tworzyć funkcję. Dalej mamy jej nazwę, a za nią nawiasy. W ramach tych nawiasów możemy podać listę argumentów, których nasza funkcja oczekuje, choć może być i tak, że takie argumenty nie są do jej działania potrzebne, wówczas zostawimy te nawiady puste. Potem następuje właściwa część kodu, która będzie wykonywana zawsze, kiedy w naszym programie wywołamy tę właśnie funkcję. Może się też pojawić słowo kluczowe return, jeśli zakładamy, że w efekcie działania funkcja zwróci jakiś wynik, choć często będzie ono pomijalne. Całość zaś zamyka słowo kluczowe end.

Wprawdzie funkcje, jakie zademonstrowane zostały przez autorów tutorialu, który stanowi podstawę mojego cyklu wpisów Robloxowi poświęconych, nie zakładają otrzymania argumentów z zewnątrz (deklaracja użytych tam funkcji pozostawiają puste miejsce między nawiasami), to w przypadku niniejszego wprowadzenia do zagadnienia funkcji skupię się w całości na przeciwnym podejściu. Zaczniemy od prostej funkcji, która dokonuje sumowania dwóch liczb. Oto przykład takiego kodu:

local function suma (liczba1, liczba2)

local wynik = liczba1+liczba2

return wynik

end

Jak widać nasza funkcja nazywa się suma i oczekuje ona, że przy jej użyciu przekazane zostaną dwa argumenty, co zostało zasygnalizowane przy pomocy umieszczenia w nawiasie dwóch wartości o nazwach liczba1 oraz liczba2. Nazwa tych argumentów nie ma większego znaczenia, więc równie dobrze mogłaby to być litery a i b rozdzielone przecinkiem, ale opisanie ich w taki sposób ułatwia zrozumienie funkcji. Natomiast ważne jest jest, że niezależnie od tego jak nazwiemy te argumenty, to w ciele naszej funkcji musimy się odwołać do tych nazw właśnie, jeśli chcemy cokolwiek z nimi zrobić. W tym konkretnym wypadku do zmiennej wynik przypisujemy operację dodawania tych dwóch argumentów i na końcu zwracamy wartość tej zmiennej, czyli sumę tych dwóch liczb.

W jaki sposób możemy sprawdzić, czy funkcja działa zgodnie z naszymi założeniami? Wystarczy ją wywołać, czyli po prostu w kodzie wskazać nazwę tej funkcji i w nawiasach umieścić dwie liczby rozdzielone przecinkiem. Całość mogłaby wyglądać tak:

local function suma (liczba1, liczba2)

local wynik = liczba1+liczba2

return wynik

end

print(suma (3, 6))

Na marginesie dodam, że jeśli definicja funkcji nie zakłada przekazania do niej żadnych argumentów, to jej wywołanie odbywa się tak samo, z tym że wówczas pomiędzy nawiasami nic nie wstawiamy, czyli przy założeniu braku wymaganych argumentów w naszej funkcji wyglądałoby to tak: suma ().

Skoro jako tako zapoznaliśmy się z funkcjami, pora nieco zoptymalizować ćwiczenie, które rozpoczęliśmy przy okazji wpisu o zmiennych. Dla przypomnienia: obliczaliśmy wówczas czas potrzebny na dotarcie światła ze Słońca na naszą planetę w trzech scenariuszach, czyli w momencie, gdy Ziemia znajduje się najbliżej oraz najdalej Słońca oraz dla średniej odległości. Wówczas każdą operację wyliczyliśmy osobno. Teraz do tego użyjemy funkcję. Niżej całość kodu i kilka słów komentarza.

local a = 152000000 --odległość w kilometrach w aphelium (największy dystans)

local p = 147100000 --odległość w kilometrach w peryhelium (najmniejszy dystans)

local sr = 149600000 --średnia odległość od Słońca w kilometrach

local function czas (x)

local wynik =x/299792

print(wynik)

end

czas(a)

czas(p)

czas(sr)


Początek jest identyczny, czyli deklarujemy 3 zmienne odpowiadające odległości Ziemi od Słońca dla każdego z trzech wspomnianych scenariuszy. Później zamiast jednak wyliczać czas dla każdego przypadku definiujemy funkcję o nazwie czas, który oczekuje jednego argumentu (tutaj oznaczonego jako x). Wartość ta następnie jest dzielona przez liczbę 299792, która w przybliżeniu odpowiada prędkości światła wyrażonej w kilometrach na sekundę. W kolejnym kroku zaś wywołujemy inną funkcję, czyli print, tak by nasza funkcja od razu odpowiadała również za wyświetlenie wyniku. Trzy ostatnie wiersze to wywołanie funkcji czas, do której jako argument przekazujemy po kolei trzy zmienne odpowiadające odległości Ziemi od Słońca.

I to byłoby wszystko na dzisiaj. Rzecz jasna niniejszy wpis, jak wszystkie pozostałe w tym cyklu poświęcone Lua, nie wyczerpuje tematu funkcji, tym niemniej wydaje mi się, że najbardziej podstawowe elementy tej struktury programistycznej zostały z grubsze omówione. Na koniec zasugeruję, by w praktyce stosować funkcje nawet wówczas, jeśli wiemy, że nie zastosujemy jej w naszym skrypcie/programie więcej niż jeden raz. Takie rozwiązanie poprawia czytelność kodu, a jeśli przy tym stosujemy opisowe i czytelne nazwy funkcji, to rzut oka na samą nazwę powie nam, co dana funkcja ma za zadanie robić.