I have been using lua for a while. (About 4 years as of writing this!)
It's a language that I kinda grew up on, and I've learned to love.
This article will contain a list of idioms that are common to see in lua.
Lets go!
Default values with or
local x = obj.x or 15
-- in lua, accessing an undefined table value defaults to `nil`.
-- `nil` and `false` are falsey values,
-- So in this example,
-- If `obj` doesnt have the `.x`, then it will fall back to 15.
-- another common use case:
obj.x = obj.x or 0
Optional arguments:
In lua, passing less or more arguments doesn't error.
local function f(x)
print(x)
end
f(1,2,3) -- this is fine. output: 1
f() -- this is fine. output: nil
We can use this to have optional arguments:
-- euclidean distance:
local function distance(x, y, z)
z = z or 0 -- z is an optional argument!
local dx, dy, dz = x*x, y*y, z*z
return (dx+dy+dz) ^ 0.5
end
print(distance(3,4)) -- 5
print(distance(3,4,5)) -- 7.071
Error on undefined access
In lua, if you access an undefined variable, that variable returns nil. Example:
print(undefined_variable_34389439) -- nil
-- no error!
This is a bit weird, and some people don't like it.
But we can change this with __index
and setmetatable
.
In lua, _G
is the special table that holds all the globals.
local function err(t,k,v)
error("Accessed an undefined variable: " .. tostring(k))
end
setmetatable(_G, {
__index = err
})
Now, if we access an undefined variable:
print(undefined_variable_34389439)
-- Error: main.lua:4:
-- Accessed an undefined variable: undefined_variable_34389439
You can do the same with __newindex
if you want to stop pollution of the global namespace on accident.
Private class methods
For the OOP folks out there, who want private methods.
Often in lua, you'll see a class setup like so:
local MyClass = Class()
function Class:init()
self.x = 0; self.y = 0
end
function Class:privateHi()
-- ugh, I wish this could be private!
print(self)
end
function Class:hi()
self:privateHi()
print("hiiii")
end
Private methods can be done like so.
local function privateHi(self)
-- yay, now i am private!
print(self)
end
function Class:hi()
privateHi(self)
print("hiiii")
end
At first, you may feel uneasy doing it this way, or you may feel cheated.
Realize though, that all functions in lua are anonymous and first-class. privateHi
has the exact same bytecode as Class:privateHi
:
0000 FUNCF 4
0001 GGET 1 0 ; "print"
0002 MOV 3 0
0003 CALL 1 1 2
0004 RET0 0 1
The only difference is that one is inside a table, and one is a local.