Czytany Wpis

Absolutne podstawy Lua. Odsłona pierwsza

Wprowadzenia do podstaw języka Lua. W tym wpisie będzie trochę o typach i operatorach.

Absolutne podstawy Lua. Odsłona pierwsza

W przyszłym roku językowi Lua stuknie 30-ka, choć szerszej publiczności objawił się nieco później i w związku z tym zazwyczaj datuje się jego narodziny na rok 93 ubiegłego stulecia. Tym niemniej pracę nad nim zaczęły się właśnie w 1992 roku, a ponieważ zapowiedź zbliżającej się okrągłej rocznicy jakoś bardziej przemawia do wyobraźni i poniekąd podnosi znaczenie tematyki podjętej w tym wpisie, to przymkniemy chwilowo oko na tę drobną faktograficzną nieścisłość.

Żeby było jeszcze ciekawej wspomnę, że w pewnym sensie język ten ma “dysydenckie” korzenie, czyli mówiąc po ludzku: jego powstanie było owocem ówczesnej sytuacji politycznej, która “ciemiężyła” brazyliskich twórców oprogramowania. Otóż w latach 1977-1992 w Kraju Kawy obowiązywały bardzo restrykcyjne bariery, jeśli chodzi o użytkowanie sprzętu i oprogramowania komputerowego innego niż rodzimego pochodzenia. W odpowiedzi na te niedostatki trójka młodzieńców na potrzeby realizowanego przez nich projektu postanowiła przygotować - całkowicie od podstaw - zestaw niezbędnych narzędzi, które wydawały się niezbędne do osiągnięcia założonego celu. Tym sposobem w 1993 roku światu objawił się języka Lua, który dzisiaj jest głównym przyczynkiem do “koderskiej” chwały jego twórców, choć z punktu widzenia ich projektu był raczej dodatkiem niż centralnym elementem całego przedsięwzięcia.

Tym niemniej dzięki względnej prostocie oraz dostępności dla różnych platform komputerowych Lua zyskał w ciągu kilku lat sporą popularność. Choć trzeba też otwarcie przyznać, że nigdy nie zbliżył się do poziomu powodzenia, jakie cechuje obecnie najbardziej znane języki skryptowe, czyli Python oraz JavaScript, choć te ostatnie również powstały w latach 90-tych ubiegłego stulecia. Co jednak ciekawe Lua szczególnie upodobali sobie twórcy gier, ponieważ oprócz Robloxa, o którym ostatnio piszę na tym blogu, można wymienić w tym kontekście między innymi Garry's Mod, World of Warcraft czy serię gier FarCry. Jednakże na początek przygody z kodowaniem osobiście rekomendowałbym raczej wspomnianych przed momentem “konkurentów” i to bynajmniej nie z tego powodu, że są mi znacznie lepiej znane niż Lua. Pech jednak chciał, że Roblox Studio wspiera wyłącznie tego ostatniego i trzeba z tym sobie jakoś radzić. By jednak przesadnie nie narzekać, do czego z resztą mam naturalne ciągotki (blogowy pseudonim nie jest bynajmniej dziełem przypadku), przejdźmy do meritum dzisiejszego tekstu, czyli bardzo krótkiego wprowadzenia do tego języka, rzekłbym czegoś na kształt zajawki.

Otóż Lua - jak już wcześniej na marginesie wspomniałem - zaliczany jest do rodziny języków skryptowych, czyli takich które służą w pierwszym rzędzie do automatyzacji pewnych powtarzalnych lub żmudnych zadań, nierzadko realizowanych w ramach innej, bardziej złożonej aplikacji czy całego ekosystemu oprogramowania. Tym niemniej nie definicje i klasyfikacje tutaj są najistotniejsze. Ważniejsze z praktycznego punktu widzenia jest to, że tego rodzaju języki są zazwyczaj łatwiejsze do nauczenia, a przy tym relatywnie prosto pisze się w nich kod, choć raczej rzadko tworzy się gotowe i złożone aplikacje (o grach nie ma nawet specjalnie sensu w tym kontekście wspominać), a przynajmniej takie, które następnie trafiają do masowego odbiorcy.

Ta charakterystyka jak ulał pasuje do Lua, który dzisiaj głównie wykorzystywany jest do pracy w ramach innych aplikacjami i właściwie chyba nigdzie indziej. Tym samym by z niego skorzystać poza środowiskiem “żywiciela” (ot choćby w rodzaju Roblox Studio) konieczny jest interpreter, czyli wyspecjalizowany program, który spełnia rolę “tłumacza”, tj. przekłada w locie instrukcje napisane w Lua na polecenia zrozumiałe dla komputera, na którym pracujemy. Na szczęście w ramach tego wprowadzenia nie ma potrzeby instalowania czegokolwiek na naszych maszynach - ot skorzystamy po prostu z jednego z dostępnych internetowych “placów zabaw” (playground) dla Lua. Sporo tego jest w sieci, ja zaś po prostu używam tego, który jest dostępny na oficjalnej stronie projektu odpowiedzialnego za rozwój tego języka. Skorzystać z niego możecie klikając w ten link.

Dzisiaj będzie naprawdę krótko, ponieważ dopiero muszę wymyślić lub - jeszcze lepiej - zapożyczyć z innego źródła ciekawe przykłady, dzięki którym będziemy mogli zapoznać się z podstawami “koderskiego” fachu, takimi jak instrukcje warunkowe, pętle oraz funkcje, czyli wszystkim tym, co będzie potrzebne w planowanej drugiej części kursu Roblox Studio. Dlatego dzisiaj będzie trochę o wbudowanych typach oraz operatorach, a dokładniej operatorach arytmetycznych, dzięki którym będziemy mogli wykonywać proste zadania matematyczne.

By jednak to wszystko było możliwe musimy nieco uprzedzić fakty i wykorzystać dwie funkcje, które postaram się omówić szerzej w kolejnym tekście. W tym wypadku chodzi o funkcje o nazwie print oraz type. Ta pierwsza pozwala na wyświetlanie komunikatów na ekranie (w naszym przypadku efektów działania poleceń, którymi będziemy się posługiwać), zaś druga funkcja pokazuje typ danych, z jakimi mamy do czynienia.

Typy

A skoro przy typach już jesteśmy, to w Lua - jak w każdym szanującym się języku programowania - mamy ich kilka do dyspozycji. W dokumentacji można przeczytać bodajże o 8 rodzajach, ale nas tak naprawdę interesowały będą tylko trzy z nich, choć wspomnę również o czwartym, mając nadzieję, że wiedza taka może się komuś w przyszłości przydać.

Skoro wcześniej już sygnalizowałem, że dzisiaj głównie będziemy zajmować się operacjami na liczbach, to pierwszym z nich jest typ numeryczny (z angielskiego number). W niektórych językach dla reprezentowania liczb przewiduje się kilka różnych typów, jednak w przypadku Lua wszystkie one podpadają pod ten jeden typ, czyli właśnie number.

Kolejny ważny typ to string, ale nie należy tego mieszać z bielizną (głównie damską), ponieważ chodzi tutaj po prostu o ciąg dowolnych znaków (liter, cyfr oraz znaków specjalnych). Czasem mówi się w tym kontekście o typie tekstowym, ale to nie do końca precyzyjne określenie, a przynajmniej może to wprowadzać w błąd nieobeznanych z tematem, ponieważ bardziej tutaj chodzi o ich sposób zapisu tych znaków w pamięci komputera i w rezultacie cyfry oraz całe liczby - o ile je odpowiednio “spreparujemy” - mogą być do tego typu danych zaliczone. W przypadku Lua wystarczy bowiem użyć znaków cudzysłowu, by symbol cyfrowy nagle straciły status liczby właśnie. Tym sposobem zapis cyfry dwa w rodzaju “2” nie jest równoważny  zapisem bez cudzysłowu. Ktoś może pomyśleć, że to mało istotny detal, ale może on mieć niebagatelne znaczenie dla działania kodu, ponieważ w niektórych językach nie da się dokonywać pewnych operacji z użyciem różnych typów danych.

Niestety Lua pozwala na całkiem sporo w tym zakresie i choć nie da się sumować ciągu znaków “dwa” oraz liczby 2, to  bez problemu możemy policzyć ile to jest “2” + 2 . Dlaczego napisałem “niestety” o tym za chwilę, teraz zaś w ramach ćwiczenie proponuję wpisać i uruchomić następujący kod:

print(type(2))

print (type("2"))

print(type "dwa")

print (2 + “2”)

W efekcie powinniśmy zobaczyć na ekranie informację, że pierwsza z wartości to faktycznie liczba (number), zaś kolejne dwie to łańcuchy znaków (string), zaś efektem dodawania liczby oraz łańcucha znaków jest w tym przypadku liczba 4.

Kolejnym szalenie istotnym typem jest typ logiczny (boolean), który przyjmuje dwie wartości, tj. prawdę (true) lub fałsz (false). Jest on podstawą instrukcji warunkowych oraz przynajmniej części pętli, więc będziemy mieli jeszcze okazję się przyjrzeć mu dokładniej. Tutaj wspominam o nim między innymi, by pokazać brak pewnej konsekwencji, który przed chwilą sygnalizowałem pisząc “niestety”. Otóż jak widzieliśmy wcześniej da się zsumować liczbę 2 oraz ciąg znaków o postaci “2”. Tym niemniej jeśli postawimy między nimi znak równości (w Lua przyjmuje on postać “==”), w odpowiedzi otrzymamy wartość “false”, czyli informacje, że są to jednak różne wartości.

print (2 ==”2”)

Już na sam koniec bardzo krótko wspomnę o ostatnim z typów, które chciałem dzisiaj zaprezentować. Chodzi mianowicie o typ nil, który oznacza brak wartości albo dokładniej: wartość pustą. Nie jest to bynajmniej równoważne z wartością zerową, ponieważ zero zapisane jako 0 jest typu number i podlega wszelkim regułom dla tego typu danych obowiązującym. Natomiast wartość typu nil oznacza brak oczekiwanej wartości i to jest dość częsta sytuacja w przypadku działania chyba każdego bardziej złożonego programu, gdy w trakcie wykonywania kodu nie otrzymujemy spodziewanej odpowiedzi i taki scenariusz trzeba jakoś obsłużyć. Ale to już insza bajka, choć w naszym przypadku nie ma to większego żadnego znaczenia, jednakże podejrzewam, że w środowisku Robloxa jednak będą się takie przypadki trafiać, choć może niekoniecznie w ramach kolejnych wpisów, gdzie kodować będziemy w środowisku Roblox Studio.

Operatory

Mam jednak niejasne przeświadczenie, że mimo wszystko zbyt dużo miejsca poświęciłem typom dostępnym w Lua, oczywiście w kontekście wprowadzenia do tworzenia skryptów dla Robloxa, zwłaszcza że same w sobie są one mało ciekawe i zabawa zaczyna się dopiero w momencie, gdy możemy coś z nimi zrobić. Do tego właśnie służą - między innymi - właśnie operatory. Te ostatnie to zazwyczaj proste symbole, przy pomocy których w naszym kodzie dokonujemy pewnych operacji na dwóch lub większej liczbie elementów.

Dzisiaj akurat pochylimy się nad operatorami arytmetycznymi, czyli takimi, które służą - jak sama nazwa wskazuje - do pracy z liczbami, zaś w kolejnym wpisie nieco miejsca poświęcimy operatorom logicznym. Jednak dobrze już teraz mieć świadomość, że te dwa rodzaje operatorów nie wyczerpują całości tematu.

Jeśli chodzi o Lua, to dokumentacja wymienia 8 rodzajów operatorów arytmetycznych, natomiast w tym wpisie ograniczymy się do 4 podstawowych, z który zazwyczaj korzystamy w codziennym życiu, czyli będzie to operator:

Przy ich pomocy możemy dokonywać obliczeń analogicznie jak w przypadku każdego kalkulatora, a nawet lepiej, bo możemy uwzględnić bez problemu kolejność działań. Ponieważ dodawanie mamy już za sobą proponowałbym zacząć od trzech prostych przykładów:

print(5-2)

print(5*2)

print(5/2)

by następnie przejść do nieco bardziej złożonych:

print(10-2*3)

print(10+2*3)

W tym drugim wypadku interpreter Lua uwzględnił właściwą kolejność działań, o której uczymy się już w szkole podstawowej, czyli dzielenie i mnożenie wykonujemy zawsze przed dodawaniem oraz odejmowaniem.

Oczywiście tę naturalną hierarchię możemy zaburzyć przy użyciu nawiasów, tak jak w przykładach poniżej:

print((10-2)*3)

print((10+2)*3)

których wynik mimo użycia tych samy wartości oraz operatorów jest zdecydowanie inny niż w przykładzie wyżej.

W sumie to byłoby wszystko na dzisiaj. Dawka informacji, która została zawarta w tym wpisie z pewnością nikogo na kolana nie rzuci, ale bez tego ciężko ruszyć dalej. Mogę jednak obiecać, że w kolejnym wpisie zajmiemy się bardziej złożonymi elementami koderskiego fachu.