Intro
Na wstępie powiem, że bardzo mało programowałem w Lua. Zrobiłem tą super prostą grę, i obecnie pracuję nad inną. Jednak to wystarczyło, abym zobaczył niektóre z minusów programowania w Lua.
Zażalenia
Tutaj są moje trzy główne zażalenia:
1) Dynamiczne i (trochę) słabe typowanie
2) Wszystko jest błędem runtime
3) Brak klas
Przykłady
Dynamiczne typowanie/brak adnotacji typu
Rozważmy funkcję jako konkretny przykład.
function Ent:update_state(cmd, params) if cmd == 'at' then self.x, self.y = params.x, params.y endend
Po pierwsze, czytanie samej funkcji staje się trudne. Co ta funkcja przyjmuje? I co zwraca, jeśli w ogóle? Nie uzyskamy tych informacji patrząc na sygnaturę funkcji. Zamiast tego, musimy przeczytać ciało funkcji. Dla prostych funkcji jest to w porządku. Ale dla dłuższych i bardziej złożonych funkcji, określenie typu zwracanego staje się większym kłopotem.
Ponadto, czytanie/pisanie/debugowanie wywołań funkcji staje się trudne. Możemy przekazać wartość dowolnego typu do cmd
! Jeśli uruchomimy ent:update_state(4, …)
, ent
nie zostanie zaktualizowane. Ale zamiast wyłapać to jako błąd typu, będziemy musieli debugować to w czasie działania.
Ogólnie rzecz biorąc, języki z dynamicznym typowaniem są trudniejsze do odczytania. Jeśli chcesz znać typ zmiennej, musisz pomyśleć o ścieżce wykonania kodu, zamiast być w stanie rzucić okiem na adnotację typu (np. Java) lub sprawdzić typ w REPL (np. używając ghci do sprawdzenia typów Haskella). Język Hack jest jednym z wyjątków. Jest on dynamicznie typowany, ale wciąż zapewnia statyczne sprawdzanie typów. Z Lua, otrzymujesz wszystkie zalety i wady dynamicznie typowanego języka. Bardzo łatwo jest pisać kod i równie trudno zapewnić jego poprawność.
Runtime/Silent Errors
function test_func(test_arg) print(test_arg)endtest_func() -- prints 'nil'
Oto scenariusz, z którym często się spotykam. Muszę dodać/usunąć/zmienić jakąś funkcję. Zmieniam więc funkcję, a następnie obchodzę ją i zmieniam wszystkie wywołania. To nie jest takie złe; mogę przeszukać cały projekt i aktualizować wywołania jedno po drugim. Ale co jeśli pominę jedno z nich? Albo co jeśli dodam nowe wywołanie i zapomnę, że zmieniłem funkcję? Zgadłeś: awaria runtime!
Rybki inny przykład: 4 / 0 = inf
. Nie wyrzuca błędu.
No Classes
Jest jeszcze ten, który działa dobrze. Ale wciąż brakuje mu wielu fajnych cech OO: widoczności metod i interfejsów, by wymienić tylko kilka. Bez tych pierwszych, bardzo łatwo jest zmienić stan obiektu z dowolnego miejsca w kodzie, i znacznie trudniej jest rozumować o stanie obiektów.
Nie wszystko jest złe
Ok, to wszystkie przykłady jakie mam (na razie). Właściwie nauczyłem się przyzwoitego kawałka podczas pisania tego. Miałem zamiar narzekać na globalne skalowanie, ale znalazłem to. Miałem zamiar narzekać na wymuszanie typów, ale nie jest to zbyt złe (dzieje się to tylko z ciągami i ints). I okazuje się, że istnieje typowana wersja Lua! Nie próbowałem jej jeszcze, ale wygląda obiecująco. Jeśli to czytasz i próbowałeś typedlua, daj mi znać w komentarzach jak to jest.
Dlaczego narzekam?
Zdaję sobie sprawę, że narzekanie na te wszystkie rzeczy może wydawać się głupie. Lua jest lekkim językiem skryptowym; rzeczy, które wymieniłem powyżej nie zawsze są wady. Lua nie jest przeznaczona do budowania dużych, złożonych aplikacji. Ale właśnie dlatego piszę o tym na podreddicie Love2D. Wygląda na to, że ludzie robią całkiem duże i złożone gry z Lua i Love2D. Na przykład, Mari0, Warlock’s Tower, itp. Jak oni (ty?) to robią? Nie mogę sobie wyobrazić robienia „legalnej” gry w Lua/Love2D. Gdybym zrobił sobie przerwę na tydzień, prawdopodobnie zapomniałbym połowy kodu i straciłbym zbyt wiele czasu próbując rozgryźć typy wszystkich moich zmiennych i funkcji. Czy gry zazwyczaj używają Lua jako języka „kleju”, a resztę implementują w C/C++? Czy tworzenie dużych gier w Lua jest łatwiejsze niż w innych językach, nawet z problemami, które wymieniłem powyżej? W jaki sposób ludzie używają Lua do dużych gier, jeśli w ogóle to robią?
Dzięki za poświęcenie czasu na przeczytanie tego :D. I jeśli coś pomyliłem powyżej, proszę daj mi znać!
Interesujące lektury:
Lua: Dobre, złe i brzydkie części
Słabe i mocne typowanie
.