Chris Collins

Lab · Playground

Lua playground

Lua 5.4 running as WebAssembly — coroutines, metatables, and string patterns you can edit and run.

Code blocks on this page are editable — change them and press Run.

Lua is the small, fast scripting language embedded in everything from games and Neovim to network gear and ESP32 firmware. These blocks run the real Lua 5.4 interpreter compiled to WebAssembly (wasmoon) in a Web Worker. Each run starts a fresh interpreter.

Coroutines as generators
local function fibonacci()
  return coroutine.wrap(function()
    local a, b = 0, 1
    while true do
      coroutine.yield(a)
      a, b = b, a + b
    end
  end)
end

local next_fib = fibonacci()
local out = {}
for i = 1, 15 do out[i] = next_fib() end
print(table.concat(out, ", "))
Metatables: a 2-D vector type with operators
local Vec = {}
Vec.__index = Vec

local function vec(x, y) return setmetatable({ x = x, y = y }, Vec) end

Vec.__add = function(a, b) return vec(a.x + b.x, a.y + b.y) end
Vec.__mul = function(a, k) return vec(a.x * k, a.y * k) end
Vec.__eq = function(a, b) return a.x == b.x and a.y == b.y end
Vec.__tostring = function(v) return string.format("(%g, %g)", v.x, v.y) end
function Vec:length() return math.sqrt(self.x ^ 2 + self.y ^ 2) end

local a, b = vec(3, 4), vec(1, 2)
print("a + b    =", a + b)
print("a * 2    =", a * 2)
print("|a|      =", a:length())
print("a == b   =", a == b, " a == vec(3, 4) =", a == vec(3, 4))
String patterns: count the words in a passage
local text = [[
Lua is a powerful, efficient, lightweight, embeddable scripting language.
It supports procedural programming, object-oriented programming,
functional programming, data-driven programming, and data description.
]]

local counts = {}
for word in text:lower():gmatch("%a+") do
  counts[word] = (counts[word] or 0) + 1
end

local words = {}
for w, n in pairs(counts) do words[#words + 1] = { w = w, n = n } end
table.sort(words, function(a, b) return a.n > b.n or (a.n == b.n and a.w < b.w) end)

for i = 1, 5 do io.write(string.format("%-12s %d\n", words[i].w, words[i].n)) end