
A single conceptual lecture that traces the birth of Lua at PUC-Rio in 1993, framed against the trade embargoes that pushed Brazilian engineers to invent their own scripting tool instead of importing one. You'll follow a visual timeline of Lua's quiet three-decade march from its origins to the modern versions, then land on a definition card that captures Lua's tagline in three words: small, fast, and embeddable. You'll also learn why the name means "moon" in Portuguese. No code anywhere; this is pure narrative and timeline.
A runnable first lecture where you'll see a one-line Lua program emit "Hello, Moon" to the console, then watch the same idea expressed with io.write so the difference between print's automatic newline and io.write's raw output becomes clear. You'll see how print handles several values at once and how io.write lets you build output piece by piece, like a loading bar. The console output makes the newline behavior visible so the distinction lands in your fingertips.
You'll see the three flavors of Lua comments: single-line with two hyphens, block comments with --[[ ... ]], and the level-bracket form --[==[ ... ]==] used to safely nest closing brackets. You'll meet the famous Lua trick where adding a single extra hyphen before --[[ flips a block comment off, letting you toggle code in and out by editing one character. A small example switches between two greetings just by changing those hyphens.
Lua famously lacks built-in string interpolation, so you'll see the real-world patterns side by side: the .. concatenation operator, string.format with C-style %s and %d placeholders, and a hand-rolled gsub interpolation that pulls values from a table. You'll build a sentence about a hero's name and age three different ways and print all three so you can compare the tradeoffs, then assemble a full quest announcement using the right tool for the job.
A practical lecture showing how the same code reaches Lua through two doors: typed directly into the interactive lua REPL as a live playground, and saved into a .lua file and run with "lua script.lua". You'll watch a tiny script print its own arg[0] so you can see how Lua exposes the invocation path, and a Unix "#!/usr/bin/env lua" shebang shows how a script becomes directly executable. You'll finish by reading the full arg table to see every command-line argument a script received.
A concept-only lecture explaining Lua's core design pillars: a minimal core, mechanisms over policies, portability through ANSI C, and extension as a first-class idea. It makes Lua's smallness concrete by contrasting its tiny C reference implementation against the multi-million-line footprints of larger languages. A side-by-side comparison shows what Lua deliberately leaves out versus what it provides through tables, coroutines, and metatables, framing these as conscious tradeoffs rather than missing features. No code is shown; the lecture is about engineering philosophy.
A code lecture that creates values across Lua's types, nil, boolean, number, string, function, table, and userdata, and reports type() of each, set inside an adventure-inventory theme. You'll see how functions and tables are themselves first-class values that travel like any other value, and how userdata wraps native handles such as io.stdout. The thread type rounds out Lua's eight types and is covered later alongside coroutines. A final loop walks a roster of values to print the whole catalog at once.
A runnable snippet that defines two variables, one with local and one without, then reveals that the unprefixed name silently leaked into the global table. You'll see exactly why production Lua code almost always begins with "local" and how forgetting it is one of the most common sources of subtle bugs, demonstrated with two functions whose global writes quietly clobber each other. The fix is one word, and a closing example locks state safely inside a closure.
A demo that uses math.type() to show how Lua 5.3 introduced an integer subtype distinct from float, then prints the result of true division versus floor division to make the difference visible. You'll hit the trap where 50 and 50.0 compare equal yet math.type reports them differently. The lecture closes with a universal number inspector function that tags any value as integer or float.
You'll see the # length operator on ASCII strings, the difference between # and utf8.len on multibyte text (demonstrated with a Japanese name in katakana versus its English spelling), and Lua's long-bracket syntax [[ ... ]] for multiline literals without escape sequences. You'll print a multiline chant using long brackets and see that strings cannot be mutated in place, since calling something like :upper returns a brand-new string. The final challenge builds a multiline victory banner and reports its length.
A runnable example that walks through Lua's truthiness rule: only false and nil are falsy, while zero, the empty string, and the empty table are all truthy. Each value runs through an if-check so the surprise lands visually, with an explicit "polyglot trap" moment for developers coming from other languages. You'll then build a small truth-detector function that prints "truthy" or "falsy" for any value you hand it.
A visual tour of Lua's real-world footprint, rendered as an infographic of the industries it quietly powers: game scripting, web and networking, embedded and IoT firmware, and creative tooling. A chart shows the approximate distribution across those domains, and a companies-and-products view puts faces to the names behind the logos. The takeaway: Lua rarely stands alone as an application language, but it is the secret glue language behind countless major products. Pure concept and visualization.
A snippet that walks through Lua's arithmetic operators including floor-division // and exponent ^, then shows that "not equal" is written ~= rather than != as in most C-derived languages. Framed as hero-damage math and a duel of comparisons, it builds a grand operator calculator that runs every operator on the same pair of numbers and prints each result. By the end the ~= spelling and the floor-division and power operators are second nature.
Because Lua has no ternary operator, idiomatic code uses "a and b or c" as a substitute. You'll start with the plain "or" default (picking a default hero name when the input is nil), then see the full and-or ternary trick, then meet the subtle pitfall where the middle value being false silently breaks the idiom. You'll see both the working case and the broken case printed, and finish with the bulletproof if-else fallback for when the pattern would lie.
A runnable example that demonstrates if/elseif/else chains by grading a boss-fight score, then shows the idiomatic Lua substitute for the missing switch statement: a lookup table mapping cases to functions, fired with a single dispatch line. You'll see both a spellbook dispatcher and a battle-action dispatcher, and print results from the branching and the table-driven patterns so the cleaner approach is obvious.
A snippet that demonstrates Lua's three loop forms: while for pre-checked loops (charging a mana pool), repeat-until for post-checked loops where the condition can see locals declared in the body, and the classic numeric for with start, stop, and step. All three run so the differences in mechanics are visible. A "heist mode" finale uses a repeat-until loop to crack a vault by walking through a list of hard-coded guesses until it hits the secret number 42.
Lua has no continue keyword, so idiomatic code uses goto with a "::continue::" label at the bottom of the loop body. You'll see this skip pattern filter values from a sequence, then contrast it with a break example that exits the loop entirely. A loot-scan finale ties both together: it skips cursed items with goto continue and breaks out the moment it finds a legendary drop.
A candid lecture that refuses to oversell Lua. It walks through five genuine flaws, including 1-based indexing that frustrates polyglots, the nil-versus-absent ambiguity in tables, a tiny standard library that forces you to reach for third-party rocks, breaking changes between minor versions, and the cultural split between standard Lua and LuaJIT. Each sharp edge is paired with the rationale the maintainers give, so you understand these as design choices rather than oversights, ending with an honest take on where Lua earns its keep and where it does not.
A snippet that defines a function two ways, the function-keyword form and the assignment form where a function literal is stored in a local variable, and proves they are equivalent by calling both. A spell-casting theme drives the point home, and a higher-order moment passes a function as an argument to another function so first-class status is unmistakable. You'll see an effect function applied to a boss's health to lock the idea in.
A runnable example showing a function that returns three values at once and a parallel assignment that captures them, including the classic one-line swap. It demonstrates how only the rightmost call in an expression list keeps its multiple values, and how wrapping a call in parentheses truncates it to a single value, with both behaviors printed. The finale is a divmod function returning quotient and remainder, called right inside a print so both values appear.
A snippet that defines a function with ... in its parameter list, then uses select('#', ...) to count arguments and table.pack to capture them as a table. A sum function totals damage from any size of adventuring party, printed for several different argument counts, and a combo-chaining example shows variadics working with both numbers and strings. By the end the ... token feels natural for any "accepts any number of arguments" job.
A demo that builds a make_counter function returning a closure that increments and returns a private upvalue. Calling it twice creates two independent counters whose outputs are printed interleaved to prove each closure holds its own state. This is the foundational pattern that replaces classes for state encapsulation in idiomatic Lua. The lecture extends it into a combo meter with a reset button and a configurable counter factory that accepts an initial value and a step.
A runnable snippet showing a factorial defined recursively, then exposing the hidden multiplication that prevents it from being a tail call, then rebuilding it with an accumulator into a proper tail-recursive form. Because Lua guarantees proper tail calls, the accumulator version can recurse arbitrarily deep without overflowing the stack, demonstrated by a tail-recursive sum that handles a one-million-deep call without a scratch.
A specs-and-numbers lecture rendered as dashboard and bar-chart visuals. It compares the size of the Lua interpreter binary against other dynamic-language runtimes, then introduces LuaJIT as a separate project by Mike Pall and shows benchmark bars where LuaJIT often matches or beats C in tight numerical loops, making it one of the fastest dynamic languages ever built. A quadrant chart plots languages on speed-versus-ease axes to position Lua and LuaJIT clearly. Strictly conceptual and visual.
A snippet that creates a table of string elements using array-literal syntax (a starting Pokemon squad) and prints elements by index. It highlights that Lua arrays start at 1 and that # returns the length of the sequence portion only, until it hits a nil, where behavior becomes implementation-defined. You'll punch a hole in an array to see the sparse-array trap firsthand, then iterate a clean roster in order with ipairs.
A runnable example that builds a table mapping country codes to country names, accessed with both bracket notation t["us"] and dot notation t.us. It shows that the two notations are literally the same operation and that dot notation only works for valid identifier keys, demonstrated with awkward keys like "high score" that force bracket access. You'll see several lookups, a missing key yielding nil, and a roster lookup that mixes both notations.
A snippet that iterates the same table with ipairs (sequence-only, ordered) and pairs (everything, unordered) and prints the output of each. It highlights the contract that pairs gives no order guarantees, because hash-map keys are not stored in insertion order. A mixed table with both array entries and string keys shows the "two worlds in one bag" behavior, printing just the array portion with ipairs and then everything with pairs.
A runnable demo of the four most-used table-library functions: table.insert to append or insert at an index, table.remove to delete and return, table.sort with an optional comparator, and table.concat to join into a string. All four operate on the same party-and-roster theme with results printed after each step, including a table.sort call that orders words by length using a custom comparator, and a guild-manager finale that combines all four.
A snippet that assigns a table to a second variable, mutates through one, and observes both reflect the change, proving assignment shares a reference instead of copying. It then shows how to make a shallow copy by iterating and assigning into a new table, printing the original and the copy after a mutation to prove they are independent. The lecture closes with a reusable shallow_copy helper you can drop into your own code.
A conceptual deep-dive into Lua 5.0's switch from a stack-based VM to a register-based VM. A diagram compares how a stack VM evaluates "a + b * c" versus how the register VM does it, and a side-by-side view contrasts the instruction count between the two designs. The lecture explains that the register-based design produces fewer instructions per operation and is one reason Lua benchmarks so well despite being interpreted, illustrated with a visual of the simulated register file. Strictly visual; no runnable code.
A runnable snippet that defines a producer coroutine yielding successive values and a consumer loop that resumes it to pull each one, themed as loot drops. This demonstrates the cooperative pattern that replaces generators and iterators in other languages, and shows how coroutine state persists between resumes because the call stack is preserved. The lecture finishes with an infinite Fibonacci stream coroutine and a driver loop that prints term after term on demand.
A snippet that builds a stateless iterator function for traversing a table in reverse order and drives it with generic for. It explains the generic-for protocol, an iterator function plus a state and a control value, and prints the elements of a list walked backward. The lecture then builds an even-indexed iterator that yields only every second element, driven the same way, so you can write your own iterators with confidence.
A code demo that defines a Vector "class" as a table with a metatable, overloads __add so v1 + v2 works, and uses __index so instances can find their methods. You'll print the result of adding two vectors and calling a method on the result, the canonical idiomatic way to build OOP-flavored code in Lua. A full "rocket launch" example assembles the whole pattern end to end, including a metamethod for clean formatted output.
Lua ships no functional utilities, so this lecture writes map, filter, and reduce as pure-Lua functions over arrays and then chains them into a pipeline. A snippet takes a list, filters by a predicate, transforms the survivors via map, and folds them into one value via reduce, printing the result. By the end you can build your own higher-order helpers instead of reaching for a library.
A snippet that wraps a risky function call in pcall and prints both the success boolean and the result or error message. It then upgrades to xpcall with a handler that adds a stack traceback via debug.traceback, printing the full call chain of a deliberately raised error. The finale is a safe_divide function that catches a divide-by-zero attempt and returns a clean error instead of crashing.
A runnable demo of two micro-optimizations that high-performance Lua relies on. First, math.sin is cached in a local before a tight loop and both versions are timed to reveal the speedup. Second, a long battle log is built by appending pieces to a table and calling table.concat once at the end, rather than using .. inside the loop, with both timings printed. A boss-report finale combines both patterns in one routine.
A concept lecture explaining the metatable as the engine behind Lua's "we don't need classes" claim. A diagram shows how accessing a missing key triggers __index, how __index can be a table or a function, and how chains of __index relationships approximate inheritance. A comparison maps classical OOP vocabulary (class, method, inheritance, override) onto the Lua equivalents (metatable, function in a table, __index chain, reassignment), and a tour of the other metamethods rounds it out. The lecture is purely conceptual, with diagrams instead of code.
A concept lecture on Lua's tri-color incremental garbage collector and the generational mode introduced in 5.4. A process diagram shows the mark, atomic, and sweep phases, and a dashboard compares pause times and throughput between incremental and generational modes on a hypothetical workload. The lecture explains the collectgarbage tuning knobs at a conceptual level without code, and ends with a checklist of warning signs that a Lua application embedded in a game or server needs GC tuning.
A diagram-driven explanation of how Lua coroutines differ from OS threads. A side-by-side view contrasts pre-emptive threading (the OS interrupts you) with cooperative coroutines (you yield voluntarily), and a timeline shows two coroutines interleaving via yield and resume. The lecture closes with guidance on when coroutines are the right tool (state machines, generators, async pipelines) versus when you genuinely need OS threads for CPU-bound parallelism. No code; concept and diagram only.
A standalone tour of LuaJIT as a separate ecosystem from reference Lua. A process diagram shows how a tracing JIT identifies hot loops and compiles them into native machine code, and a comparison contrasts standard Lua's interpreter, LuaJIT's interpreter, and LuaJIT's JIT-compiled hot paths in terms of speed. The lecture introduces the FFI library that lets LuaJIT call C functions and lay out C types with no glue code, and credits the one engineer behind a generation of speed. Purely conceptual.
A concept lecture explaining the elegance of Lua's C API, which uses a single shared stack to pass values back and forth between host and guest. A process diagram walks through a host C program pushing a function, pushing arguments, calling, and reading the result off the stack, step by step. The lecture then shows the canonical luaL_dofile pattern as it appears in real engines and firmware, and closes with how engines like Redis and Nginx wire Lua into their event loops. No code is shown; the focus is the architectural pattern.
This course contains the use of artificial intelligence.
Lua is the quiet giant of programming. It does not dominate Stack Overflow surveys or trend on social media, yet it is everywhere that matters when performance and embeddability are non-negotiable. It scripts Roblox, the largest gaming platform on Earth. It configures Neovim, the editor of choice for a new generation of developers. It glues together Redis modules, Nginx request pipelines, Adobe Lightroom plugins, and the AI behavior of World of Warcraft. Born in 1993 at a Brazilian university under software import restrictions, Lua was engineered from day one to be small, fast, portable, and unobtrusive. Learning it is not just learning a language; it is learning how a great language can do more with less.
This course takes you from your very first print statement to the deep internals that make Lua special. It is built as six hands-on sections, and each coding section opens with a short conceptual lecture that sets the scene before you touch the keyboard. You will start with the origin story, the design philosophy, and where Lua actually runs in production. You will then build solid foundations in syntax: the built-in types, local versus global scoping, the curious not-equal operator, the missing switch and continue statements, and the and/or ternary idiom. You will master functions, multiple returns, variadic arguments, closures, and proper tail calls. You will explore tables, the single data structure that serves as array, hash map, object, and module all at once. Every runnable example is set in a fun, game-flavored world of heroes, loot, spells, and boss fights, so the syntax sticks while you build something you actually want to read.
The final section goes deep into the machinery that makes Lua tick, mixing runnable code with concept lectures. You will write coroutines, custom iterators, metatable-based classes, your own map/filter/reduce, and robust error handling with pcall and xpcall. Then the course closes with a run of pure-concept deep dives that sit at the very end of the journey: the metatable __index cascade as a replacement for whole object systems, the incremental and generational garbage collectors, coroutines versus OS threads, LuaJIT with its FFI and tracing compiler, and finally how Lua is embedded in C through its elegant stack-based API. You finish with a clear mental model of both how to write Lua and how Lua works underneath.
This course is for developers who already know at least one other language and want to add a sharp, focused, embeddable tool to their belt. Game developers targeting Roblox or Love2D, Neovim users writing their own plugins, backend engineers extending Redis or Nginx, embedded systems programmers, and anyone curious about minimalist language design will all find direct value. By the end you will read idiomatic Lua fluently, write your own modules, debug with pcall, profile with confidence, and understand exactly when Lua is the right answer and when it is not.
What sets this course apart is honesty and depth in equal measure. We do not pretend Lua is perfect; we name its sharp edges upfront, including 1-based indexing, the nil-versus-false truthiness rule, and the lack of a standard library compared to Python. We also do not stop at surface syntax. You will leave understanding the register-based VM, the __index cascade, and why local caching of globals matters for hot loops. Enroll now and add one of the most elegant, influential, and quietly powerful languages in computing to your toolkit.