Lua ist eine unterschätzte Sprache
(nflatrea.bearblog.dev)- Je mehr man über das Design und die Implementierung von Lua lernt, desto beeindruckender wirkt die Sprache. Es ist selten, dass Software mit so wenig Code so viel leisten kann.
- Dennoch hat Lua nicht so viel Marketing und Aufmerksamkeit erhalten wie andere Sprachen. Deshalb kennen nur wenige Entwickler die Funktionen und Vorteile von Lua.
- Sie wird meist als Nischensprache wahrgenommen, die vor allem in Spielen und eingebetteten Systemen verwendet wird.
[Merkmale und Vorteile von Lua]
Eine leicht verständliche Sprache
- Lua ist eine freie, reflektive, imperative Skriptsprache. Sie wurde 1993 entwickelt und so entworfen, dass sie in andere Anwendungen eingebettet und dadurch erweitert werden kann.
- Das Design ist sauber, und der Code ist schnell. Die C API ist leicht zu verwenden und bietet gute Performance.
- Die Syntax ist kompakt und minimalistisch, sodass auch Einsteiger leicht Zugang finden.
Hervorragende Einbettbarkeit
- Lua wurde so entworfen, dass sie sich leicht in Anwendungen einbetten lässt, die in anderen Sprachen geschrieben sind, insbesondere in C und C++.
- Damit ist sie eine ausgezeichnete Wahl für Skripting und Erweiterungen in Spielen und Embedded-Anwendungen.
- Beispiel: Lua in ein C-Programm einbetten
#include <lua.h> #include <lauxlib.h> #include <lualib.h> int main() { lua_State *L = luaL_newstate(); luaL_openlibs(L); luaL_dofile(L, "./myscript.lua"); lua_close(L); return 0; }
Unterstützung mehrerer Programmierparadigmen
- Lua unterstützt eigenständig oder mit passenden Bibliotheken imperative, funktionale und objektorientierte Programmierung.
- Das bietet die Flexibilität, den Programmierstil passend zu den eigenen Anforderungen zu wählen.
[Mögliche Nachteile von Lua]
Indexierungskonvention
- In Lua beginnt die Indexierung normalerweise bei 1, doch das ist nur eine Konvention. Arrays können mit 0, negativen Zahlen oder anderen Werten indiziert werden.
- Lua hat eigentlich keine echten Arrays, sondern nur Tabellen, die immer Key-Value-Hashes sind und daher mit 0, negativen Zahlen oder anderen Werten indiziert werden können.
- Die Standardbibliothek und eingebaute Funktionen gehen von arrayähnlichen Tabellen aus, deren Indizes bei 1 beginnen.
Fehlerbehandlung
- Die Fehlerbehandlung in Lua ist für Entwickler aus anderen Sprachen möglicherweise nicht intuitiv.
- In Lua können Fehler als Werte behandelt werden. Mit
pcalllassen sich Fehler abfangen.function risky_function() error("Something went wrong!") end local status, err = pcall(risky_function) if not status then print("Error: " .. err) end
Durch nil terminierte Arrays
- Arrays in Lua (Tabellen, die als Arrays verwendet werden) enden, sobald sie auf einen
nil-Wert treffen, was zu unerwartetem Verhalten führen kann.local arr = {10, 20, 30, nil, 50} for i, v in ipairs(arr) do print(v) -- Ausgabe: 10, 20, 30 (stoppt bei nil) end - Die Funktion
ipairsbeendet die Iteration, sobald einnil-Wert erreicht wird. - Wenn ein Array Lücken enthält, ist es sinnvoll, statt
ipairseherpairszu verwenden. Damit lassen sich alle Einträge einschließlich der Positionen rund umniluntersuchen.
[Zusammenfassung]
- Lua ist eine leistungsfähige, effiziente und vielseitige Programmiersprache, die mehr Anerkennung verdient.
- Dank ihrer Einfachheit, Einbettbarkeit und Performance eignet sie sich für verschiedenste Anwendungen wie Spiele und eingebettete Systeme.
- Sie ist unterschätzt, aber wegen ihrer Einfachheit und Performance auf jeden Fall einen Versuch wert.
- Sie wird im Plugin-System von nvim verwendet und ist effizient.
7 Kommentare
> In Lua gibt es tatsächlich keine Arrays; es existieren immer nur Tabellen als Schlüssel-Wert-Hashs, die mit verschiedenen Werten wie 0 oder negativen Zahlen indiziert werden können.
Wegen WoW-Add-ons habe ich Lua einmal kurz benutzt, und daran erinnere ich mich als das Eindrücklichste. Für fast alle Datenstrukturen wurden anscheinend immer Tabellen verwendet.
Ich kannte nur den Namen Lua, aber nach diesem Artikel finde ich es eher nicht so toll, haha..
Ich weiß es nicht genau, aber ich habe gehört, dass die Abwärtskompatibilität zwischen den Versionen furchtbar sein soll..
Persönlich würde ich sagen: Im Vergleich zu Ruby ist es bei der Frage „Läuft alter Code erst einmal noch?“ zwar etwas besser, aber gerade in 5.3 hat sich die Art geändert, wie mit
numberumgegangen wird, sodass beim Upgrade von 5.1 auf 5.3 intern jede Menge schwer nachzuverfolgender Bugs entstehen ...Außerdem gibt es viele Orte, an denen LuaJIT verwendet wird, und dort ist die Schnittstelle wiederum leicht anders, sodass genau diese kleinen Unterschiede wohl die schwerwiegendsten Probleme verursachen. Es gibt einige Bereiche, deren internes Verhalten sich unterscheidet, sodass man auch nicht wirklich viel dagegen tun kann .. =m =.
Ich habe Erfahrung damit, SmartThings-Edge-Treiber in Lua zu schreiben.
Benutzbar war es so einigermaßen, aber es war nicht wirklich eine Sprache nach meinem Geschmack.
Ich finde, dass auch die Entwicklungsumgebung bzw. das DE Teil der Sprache ist,
und zunächst wirkt es auf mich so, als sei die Community etwas zersplittert.
Es gibt auch mehrere Language Server, aber bei jedem fehlt irgendeine Funktion, oder das Code-Indexing ist langsam, und wenn Änderungen auftreten, fängt es wieder von vorn an.
Auch 1-basierte Indizierung oder Typhinweise in Kommentaren zu schreiben finde ich nicht besonders gut,
und bei den Typhinweisen schien es zudem keinen Standard zu geben, sondern sie unterschieden sich je nach Language Server.
Auch die Coroutines erinnern mich an die aus dem uralten Python ...
Embedding und FFI scheinen allerdings tatsächlich ziemlich unkompliziert zu sein.
Der Lua Language Server, den sumneko entwickelt hat, ist in letzter Zeit richtig stark
'ㅁ '...(ich glaube, er wurde 2022 oder 2023 erstellt). Das Indexing ist dabei ziemlich clever.Ich denke, die Stärke (und zugleich Schwäche) von Lua zeigt sich vor allem dann, wenn man merkwürdige Dinge machen will: Es ist absurd einfach, Methoden anderer Objekte zu überschreiben. Gerade deshalb finde ich, dass es eine wirklich gute Sprache ist, wenn man wild und spontan drauflos schreiben möchte.
Type Hinting ... wie du schon gesagt hast, gibt es zwar wirklich viele vorgeschlagene Lösungen, aber kaum eine hat sich richtig etabliert, deshalb setze ich Hoffnungen auf Luau, das vom Roblox-Team entwickelt wurde..
Hacker-News-Kommentare
Lua eignet sich gut zum Einbetten, aber die Wahl als Skriptsprache in Redis wurde stark bereut. Die Sprache selbst gefällt mir nicht. Im Vergleich zu dem, was ich auf der Ebene der Abstraktion erwarte, scheint sie viel Reibung zu erzeugen. Kleine Designentscheidungen summieren sich, sodass die Sprache etwas feindselig wirkt. Trotzdem ist sie wegen ihrer Geschwindigkeit, der einfachen Integration, des geringen Speicherverbrauchs und ihrer Zuverlässigkeit weiterhin eine überlegenswerte Wahl. Auch auf der Ebene der C-API gibt es durch den Stack-basierten Ansatz etwas Feindseligkeit. Ich war zwar schon mit Stacksprachen wie FORTH in Kontakt, aber beim Schreiben von Bindings war es trotzdem noch eine mentale Gymnastik.
Wenn man Lua mag, sollte man sich Terra ansehen. Terra ist eine Low-Level-Systemprogrammiersprache, die in Lua eingebettet ist und über Lua metaprogrammiert wird. Sie ist wie C/C++ statisch typisiert und kompiliert und erlaubt manuelle Speicherverwaltung. Anders als C/C++ wurde sie jedoch von Anfang an dafür entworfen, über Lua metaprogrammiert zu werden. Terra-Programme verwenden dasselbe LLVM-Backend, das auch für Apples C-Compiler genutzt wird. Das bedeutet, dass Terra-Code eine ähnliche Leistung wie entsprechender C-Code erzielt.
Ich habe kürzlich Lua in eine benutzerdefinierte Game-Engine integriert und kann nachvollziehen, wie sauber die Integration mit anderen Sprachen ist. Die Schnittstelle ist sauber, sodass sich Bindings leicht automatisch erzeugen lassen. Ich habe mit Roslyn Incremental Source Generators automatisch Bindings zwischen C# und Lua erzeugt, und dank des Interface-Designs war das überhaupt nicht schwierig. Durch den Lua-Stack, das dynamische Typsystem und die „Tabellen“ war es einfach, Marshaller für beliebige Datenklassen zwischen C# und Lua zu erzeugen. Trotzdem gibt es viel berechtigte Kritik an der Sprache selbst. Vor allem mag ich die 1-basierte Indizierung nicht. Während ich diese Probleme angehe, denke ich darüber nach, eine eingebettete Skriptsprache mit ähnlicher Schnittstelle zu entwerfen.
Meine Zuneigung zu Lua ist nicht größer geworden. Eher haben sich meine Beschwerden verstärkt. Es ist lange her, dass ich Lua geschrieben habe, aber ich fand es schon damals nicht intuitiv. Ich verstehe nicht, warum Arrays Tabellen sind, warum sie mit nil enden und warum sie bei 1 beginnen. Ich finde nicht, dass Lua unterschätzt wird. Zum Schreiben von Skripten in (älteren) Game-Engines ist es sehr beliebt.
Ich habe mit Lua-Plugin-Befehlen einen Chatbot gebaut, aber die Integration in ein C++-Programm war eine schreckliche Erfahrung. Ich verstehe nicht, warum Leute sagen, das Einbetten sei einfach. Man muss sehr viel am Stack manipulieren. Die Sprache selbst ist umständlich und hilft überhaupt nicht, wenn man Fehler macht. Ich werde Lua nie wieder verwenden und Projekte meiden, die Lua einsetzen.
Wegen der schwachen Typisierung, fehlender Type Hints und fehlender Fehlerbehandlung ist es ziemlich schwierig, in Lua größere Mengen Code zu schreiben. Die Sprache ist nicht unterschätzt. Mit der Zeit habe ich statisch typisierte Sprachen und Type Hints (Python, TypeScript) immer mehr zu schätzen gelernt. Es ist schädlich für eine Community, Python- oder JS-Code ohne Hints zu schreiben. Ich habe kürzlich 1,5k cloc JS in TypeScript neu geschrieben. Dabei gab es Dutzende Fälle von fehlendem null, null-Property-Zugriffen oder semantisch fragwürdigem null.
Ich denke, die meisten Anwendungen, die Skripting brauchen, sollten JavaScript einbetten. Das bringt große Vorteile durch das bestehende Ökosystem. Die Leute mögen es nicht immer, aber Millionen kennen es bereits. Man muss die Eigenheiten von Array-Indizierung und nil-Terminierung sowie Dutzende andere Dinge, die Lua erst zur Laufzeit erkennt, nicht neu lernen. Es gibt JS-Engines in allen Größen, und die meisten Betriebssysteme bieten ohne Installation zugängliche, hochwertige Engines und Embedding-Frameworks. Es ist besser, eine Standardsprache zu verwenden, statt Nutzern eine neue Sprache beizubringen. Das spart sowohl den Nutzern als auch einem selbst Zeit.
Ich habe die Arbeit mit Lua genossen und halte es für eine sehr gute Sprache. Besonders die Schnittstelle zum Einbetten in C/C++ ist sauber und flexibel. Es gibt zwar Performance-Probleme, aber wenn man bedenkt, dass Lua in High-Performance-Videospielen weit verbreitet für Spiellogik eingesetzt wird, scheinen diese Probleme lösbar zu sein. Es gibt allerdings andere Probleme, die verwirrend sind und die Sprache schwierig machen. Da das Lernen der Lua-C-Schnittstelle fast genauso umfangreich ist wie das Lernen von Lua selbst, ist der Wechsel zwischen verschiedenen Distributionen verwirrender als bei anderen Sprachen. Trotzdem halte ich die Sprache für unterschätzt.
Lua einzubetten hat Spaß gemacht, aber ähnlich wie bei wasm gab es nur selten Fälle, in denen ich neuen Code ausführen musste, ohne das gesamte Binärprogramm neu zu kompilieren. Am meisten Spaß hat es gemacht, eine Game-Engine in C++ zu bauen und die gesamte Spiellogik in Lua zu schreiben. Die schnellen Debug-Zyklen waren sehr nützlich. Am zweitmeisten Spaß hat es gemacht, einen IRC-Bot zu bauen, dessen Lua-Logik neu geladen werden konnte. Am drittmeisten Spaß hat es gemacht, Lua als Turing-vollständige Konfigurationssprache zu verwenden. Wenn ich Arrays brauchte, habe ich sie in Lua gebaut. Am wenigsten Spaß gemacht hat ein Blender-Plugin, das 3D-Modelle in generiertes Lua exportierte.
Ich finde, Lua wird überschätzt, weil es in der Spieleindustrie so weit verbreitet ist. Der einzige Vorteil von Lua ist, dass es sich leicht in C++ einbetten lässt. Ansonsten ist es ein Albtraum.