Skip to content
Volume L · The TensorCore.si Library

Lua

Tiny, fast and made to be embedded.

Lua is a small, fast scripting language designed to be embedded in other programs. It runs game logic in Roblox (as Luau), World of Warcraft add-ons and Neovim configuration, and the original Torch deep-learning framework, which inspired PyTorch, used Lua.

Prologue

Why learn Lua?

Lua has only a handful of concepts, so you can learn it in an afternoon, and it is the scripting language inside many games and tools.

  • Simple: one data structure (the table) and very few keywords.
  • Games: Roblox, LÖVE, Defold and many engines use Lua.
  • Embeddable: add scripting to C, C++ or Rust programs easily.
Prologue

Set up and run your first program

Install Lua 5.4 (or LuaJIT) from your package manager, and LuaRocks for packages.

terminal
lua -v
lua hello.lua
hello.lua
local name = "Ada"
print("Hello, AI! Welcome to Lua, " .. name .. ".")
TipUse .. to join strings. Comments start with --.
Chapter 1

Variables and types

Variables are global unless declared local, so always use local. Lua has nil, booleans, numbers, strings, functions and tables.

variables.lua
local layers = 32
local lr = 3e-4
local model = "llama3.1"
local params = 8030000000
print(model, layers, lr)
print(string.format("FP16 size: %.1f GB", params * 2 / 1e9))
print(type(model), type(nil))
Chapter 2

Control flow

Blocks end with end. Numeric for loops include both ends. Only nil and false count as false; 0 is true.

control.lua
for epoch = 1, 3 do
  print("epoch " .. epoch)
end
local bits = 8
if bits == 16 then
  print("FP16")
elseif bits == 8 then
  print("FP8")
else
  print("other")
end
local n = 3
while n > 0 do n = n - 1 end
Chapter 3

Tables

The table is Lua's only data structure: it acts as an array (1-indexed), a dictionary, an object and a module. Loop with ipairs for arrays and pairs for keys.

tables.lua
local gpus = {"H100", "H200", "B200"}       -- array
local vram = {H100 = 80, H200 = 141, B200 = 180}  -- dictionary
for i, g in ipairs(gpus) do print(i, g) end
for name, gb in pairs(vram) do
  if gb > 100 then print(name .. " has " .. gb .. " GB") end
end
print(#gpus)  -- length: 3
Chapter 4

Functions and closures

Functions are values: store them in variables and tables, pass them around, and return several values at once.

functions.lua
local function params(layers, width)
  width = width or 4096
  return 12 * layers * width * width
end
local function stats(t)
  local sum = 0
  for _, v in ipairs(t) do sum = sum + v end
  return sum, sum / #t      -- two return values
end
print(params(32))
print(stats({80, 141, 180}))
Chapter 5

Objects with metatables

Lua builds objects from tables and metatables. The colon syntax obj:method() passes the object as self.

objects.lua
local Gpu = {}
Gpu.__index = Gpu
function Gpu.new(name, vram) return setmetatable({name = name, vram = vram}, Gpu) end
function Gpu:fits(gb) return gb <= self.vram end
function Gpu:describe() return self.name .. " (" .. self.vram .. " GB)" end

local g = Gpu.new("RTX 5090", 32)
print(g:describe(), g:fits(16))
Part II · AI with Lua

AI with Lua

Lua's AI role today is in games and embedded tools: scripting NPC behaviour, calling LLMs from game servers or Neovim plugins, and running small models through bindings. Torch7, written in Lua, was one of the first popular deep learning frameworks before PyTorch.

The essential libraries

Neovim AI pluginsLua plugins that call LLMs for coding help.
lua-cjsonFast JSON encoding and decoding.
LuaSocket / lua-httpHTTP requests to model APIs.
Roblox HttpServiceCall web APIs from Roblox (Luau) servers.

Gradient descent from scratch

Learn y = 3x + 0.5 with tables and loops.

gradient.lua
local n, xs, ys = 100, {}, {}
for i = 1, n do
  xs[i] = -1 + 2 * (i - 1) / (n - 1)
  ys[i] = 3 * xs[i] + 0.5 + (math.random() - 0.5) * 0.2
end
local w, b, lr = 0, 0, 0.1
for step = 1, 500 do
  local gw, gb = 0, 0
  for i = 1, n do
    local err = w * xs[i] + b - ys[i]
    gw = gw + 2 * err * xs[i] / n
    gb = gb + 2 * err / n
  end
  w, b = w - lr * gw, b - lr * gb
end
print(string.format("w = %.2f, b = %.2f", w, b))
Part III · Build an AI agent

Build an AI agent in Lua

With LuaSocket for HTTP and lua-cjson for JSON (install both with LuaRocks), Lua can run the tool-calling loop against a local model.

Your goal→Model plans→Tool call→Your code runs the tool→Result back to model→Final answer
agent.lua
-- luarocks install luasocket lua-cjson
local http = require("socket.http")
local ltn12 = require("ltn12")
local json = require("cjson")

local function chat(body)
  local payload, out = json.encode(body), {}
  http.request{ url = "http://localhost:11434/v1/chat/completions", method = "POST",
    headers = {["Content-Type"] = "application/json", ["Content-Length"] = #payload},
    source = ltn12.source.string(payload), sink = ltn12.sink.table(out) }
  return json.decode(table.concat(out))
end

local tools = {{type = "function", ["function"] = {name = "get_weather", description = "Weather for a city",
  parameters = {type = "object", properties = {city = {type = "string"}}, required = {"city"}}}}}
local messages = {{role = "user", content = "Should I take an umbrella in Lahore today?"}}

for round = 1, 5 do
  local msg = chat({model = "llama3.1", messages = messages, tools = tools}).choices[1].message
  table.insert(messages, msg)
  local calls = msg.tool_calls
  if calls == nil or calls == json.null or #calls == 0 then print(msg.content) break end
  for _, call in ipairs(calls) do
    local args = json.decode(call["function"].arguments)
    table.insert(messages, {role = "tool", tool_call_id = call.id, content = "It is 24°C and sunny in " .. args.city .. "."})
  end
end

function is a Lua keyword, so the field must be written as call["function"].

Run it locallyInstall Ollama, run ollama pull llama3.1, and keep it running. The code talks to its OpenAI-compatible API at http://localhost:11434/v1, so the same program also works with vLLM, llama.cpp server or a cloud API by changing the URL, model name and adding an API key.
Part IV · Your path

Lua learning roadmap

Tick items off as you go. Your progress is saved in this browser.

Beginner

Intermediate

Advanced

Part IV · Your path

Projects to build

Text adventureA small game driven by tables of rooms.
LÖVE gameA 2D platformer with the LÖVE engine.
Neovim helperA plugin that sends selected code to an LLM.
Reference

Lua cheat sheet

TaskSyntax
Local variablelocal x = 1
Join strings"a" .. "b"
Table arraylocal t = {1, 2, 3}
Loop arrayfor i, v in ipairs(t) do end
Functionlocal function f(x) return x end
Method callobj:method()
Reference

Common mistakes

  • Forgetting local creates global variables by accident.
  • Arrays start at 1, and #t is unreliable if the table has holes (nil values).
  • Use ~= for not-equal, not !=.
Reference

Where to go next

On TensorCore.si: C volume, Python volume.

Keyboard: [ previous language · ] next language · / search the library