跪拜 Guibai
← All articles
Lua · JavaScript · Algorithms

Lua's 21 Keywords and One Data Structure: A JS Developer's Tour

By minorcell ·
Read original on juejin.cn ↗ Google Translate ↗ Alt translation

Lua is embedded inside Neovim, Redis, World of Warcraft, OpenResty, and Roblox. A developer who configures any of those tools is already surrounded by Lua code, and the language's table-and-metatable model is the key to reading and writing it fluently.

Summary

Lua has only 21 keywords and one composite data structure: the table. Arrays start at 1, not 0; `nil` is the sole null-ish value and doubles as a deletion mechanism; and `0` and `""` are truthy, which trips up developers coming from JavaScript. Functions return multiple values directly, and proper tail calls keep deep recursion safe.

Metatables are the language's metaprogramming backbone. `__index` provides prototype-style lookup for missing keys, forming the basis of class-like OOP without a `class` keyword. Other metamethods like `__add` and `__eq` let tables participate in arithmetic and comparison operators—a capability that remains an advanced Proxy trick in JavaScript but is everyday infrastructure here.

A full Dijkstra shortest-path implementation closes the tutorial, using nested tables as an adjacency list, `pairs` for iteration, and truthy/falsy checks in place of a visited set. The same program in JavaScript would spread across `Map`, `Set`, and plain objects; Lua collapses it all into tables.

Takeaways
Lua has 21 keywords and one data structure—the table—which serves as array, dictionary, object, and module simultaneously.
Array indexing starts at 1, not 0; the length operator `#` is unreliable on sparse arrays containing `nil`.
Only `false` and `nil` are falsy; `0` and `""` are truthy, unlike JavaScript.
Functions return multiple values directly without wrapping them in a collection.
Metatables provide `__index` for prototype-style field lookup and metamethods like `__add` for operator overloading.
Class-like OOP is achieved by setting a table's `__index` to itself and using the colon syntax for implicit `self`.
Error handling uses `pcall` (a function call), not try-catch syntax.
`require` is a runtime function that caches modules; it is not a static import statement.
Conclusions

Lua's 1-based indexing is a deliberate design choice rooted in the Fortran background of its first users, not an oversight—and the language's creator has publicly argued that 0-based indexing spread mainly through C's pointer arithmetic, a rationale that doesn't apply to higher-level languages.

The table-as-universal-data-structure design means Lua programs avoid the conceptual overhead of choosing among Array, Object, Map, and Set. A single mental model covers all of them, at the cost of losing the performance guarantees those specialized types provide in other languages.

Metatables are not an advanced feature bolted on later; they are the substrate on which Lua's own object system and operator semantics are built. This inverts the relationship seen in JavaScript, where Proxy is a power tool most developers rarely touch.

Lua's `pcall`-based error handling and runtime `require` reflect a language designed to be embedded: syntax is kept minimal, and control structures that might conflict with a host program's own error model are deferred to library functions.

Concepts & terms
Metatable
A table attached to another table via `setmetatable` that defines fallback behavior through `__`-prefixed metamethods. `__index` handles missing-key lookup; `__add`, `__sub`, `__eq`, and others overload operators.
Table
Lua's sole composite data structure. It functions as an array (integer keys starting at 1), a dictionary (string keys), and an object (keys mapping to functions). The same table instance can mix all three roles.
pcall
Protected call—a function that executes another function in a protected mode. Returns `true` plus results on success, or `false` plus an error message on failure. Lua's substitute for try-catch.
Tail call
A function call in the tail position of a `return` statement. Lua performs proper tail-call elimination, so tail-recursive functions do not grow the call stack.
Source: juejin.cn ↗ Google Translate ↗ Backup ↗