Skip to content

Lua

Lua is a powerful, efficient, lightweight, embeddable scripting language. It supports procedural programming, object-oriented programming, functional programming, data-driven programming, and data description

It is elegant

  • Lua uses "Mechanisms over Policies" i.e. it provides a small set of general mechanisms that can be used to implement a variety of policies.

Syntax

lua
-- This is a comment
--[[ This is a multi-line
     comment
-- ]]

print("Hello, World!")

Data Types

lua
local num = 42

local str = "Hello, World!"
local str2 = 'also works'
local multiline = [[
  This is a
  multi-line string
]]

local truth, lies = true, false

local nothing = nil
  • Lua is dynamically typed

  • Lua's only data structure is a table

    • It can be used as an array, maps, hash table, dictionary, collection, stack, queue, etc.
lua
-- As a list ...
local list = {
	"first",
	2,
	false,
	function()
		return "Forth!"
	end,
}

print("Yup, 1-indexed:", list[1])
print("Fourth is 4 ... :", list[4]())

-- As a map ...
local t = {
	literal_key = "a string",
	["an expression"] = "also works",
	[function() end] = true,
}

print("literal_key", t.literal_key)
print("an expression", t["an expression"])
print("a function", t[function() end])
  • Thread and Userdata are also data types in Lua

Tables

Metatables

lua
local vector_mt = {}

vector_mt.__add = function(left, right)
	return setmetatable({ left[1] + right[1], left[2] + right[2] }, vector_mt)
end

local v1 = setmetatable({ 1, 2 }, vector_mt)
local v2 = setmetatable({ 3, 4 }, vector_mt)
local v3 = v1 + v2

print(v3[1], v3[2]) -- 4 6
print(v3 + v3) -- table: 0x7f8f3b402f90

local fib_mt = {
	__index = function(self, key)
		if key < 2 then
			return 1
		end
		-- update the table, to save the intermediate results
		self[key] = self[key - 2] + self[key - 1]
		-- return the result
		return self[key]
	end,
}

local fib = setmetatable({}, fib_mt)

print(fib[5]) -- 8
print(fib[50]) -- 20365011074

-- `__index` is a fallback for table lookups
-- `__add` is a fallback for the `+` operator
-- `__newindex(self, key, value)` is a fallback for table updates
-- `__call(self, ...)` is a fallback for function calls

Functions

lua
local function hello(name)
	print("Hello, ", name)
end

local hello = function(name)
	-- .. is string concatenation operator
	print("Hello, " .. name)
end

hello("Lua")
  • Functions are first-class values in Lua
lua
local higher_order = function(value)
	return function(another_value)
		return value + another_value
	end
end

local add_one = higher_order(1)
print(add_one(2)) -- 3
  • Functions can return multiple values
lua
local returns_four_values = function()
	return 1, 2, 3, 4
end

local first, second, last = returns_four_values()

print("first:", first)
print("second:", second)
print("last:", last)
-- the `4` is discarded here
-- `first` is 1, `second` is 2, `last` is 3
  • Functions with only one argument with a string literal or a table can be called without parentheses
lua
local print_hello = function(name)
    print("Hello, " .. name)
end

print_hello "Lua"

local setup = function(opts)
	if opts.default == nil then
		opts.default = 17
	end

	print(opts.default, opts.other)
end

setup { other = 42 }
setup { default = 42, other = false }
  • Colon syntax is used to define methods
lua
local MyTable = {}

function MyTable.something(self, ...) end

-- This is equivalent to the above
-- It's just a syntactic sugar
-- `self` is a reference to the table
-- `...` is a vararg
function MyTable:anotherThing(...) end

Control Structures

Loops

  • for loop
lua
local favorite_accounts = { "3Blue1Brown", "Vsause", "MinutePhysics" }

for index = 1, #favorite_accounts do
	print(index, favorite_accounts[index])
end

for index, value in ipairs(favorite_accounts) do
	print(index, value)
end

local reading_scores = { Blue1Brown = 3, Vsause = 5, MinutePhysics = 1 }

for index = 1, #reading_scores do
	print(reading_scores[index])
end

-- Doesn't print anything - the "length" operator of tables only works for arrays

-- `pairs` is used to iterate over key-value pairs
for key, value in pairs(reading_scores) do
	print(key, value)
end

Conditionals

  • if statement
lua
local function action(loves_coffee)
	if loves_coffee then
		print("Check out `ssh terminal.shop` - it's a great place to get coffee.")
	else
		print("Check out `ssh terminal.shop` - it's a great place to get tea.")
	end
end

-- "falsey": nil, false
action() -- Same as: action(nil)
action(false)

-- Everything else is "truthy"
action(true)
action(0)
action({})
  • if-else statement
lua
local function action(loves_coffee)
    if loves_coffee == nil then
        print("Check out `ssh terminal.shop` - it's a great place to get tea.")
    elseif loves_coffee == false then
        print("Check out `ssh terminal.shop` - it's a great place to get tea.")
    else
        print("Check out `ssh terminal.shop` - it's a great place to get coffee.")
    end
end

Modules

Modules are a way to organize code in Lua. They are just tables with functions and variables.

  • There isn't anything special about modules
  • Modules are just files that return a table
lua
-- foo.lua
local M = {}
M.cool_function = function()
	print("cool function")
end

return M

-- bar.lua
local foo = require("foo")
foo.cool_function()