Two dashes start a oneline comment.
[[
Adding two ['s and ]'s makes it a
multiline comment.
]]
. Variables and flow control.
num = All numbers are ubles.
Don't freak out, bit ubles have bits
storing exact int values; machine precision is
not a problem ints that need < bits.
s = 'walternate' Immutable strings like Python.
t = "ublequotes are also fine"
u = [[ Double brackets
start and
multiline strings.]]
t = nil Undefines t; Lua has garbage collection.
Blocks are denoted with keywords like :
while num <
num = num No or = type operators.
If clauses:
num >
('over ')
else s ~= 'walternate' ~= is not equals.
Equality check is == like Python; ok strs.
io.write('not over \n') Defaults to stut.
else
Variables are global by default.
thisIsGlobal = Camel case is common.
How to make a variable local:
local line = io.read() Reads next stdin line.
String concatenation uses the .. operator:
('Winter is coming, ' .. line)
Undefined variables return nil.
This is not an error:
foo = anUnknownVariable Now foo = nil.
aBoolValue = false
Only nil and false are falsy; and '' are true!
not aBoolValue ('twas false')
'or' and 'and' are shortcircuited.
This is similar to the a?b:c operator in Cjs:
ans = aBoolValue and 'yes' or 'no' > 'no'
karlSum =
i = , The range includes both s.
karlSum = karlSum i
Use ", , " as the range to count wn:
fredSum =
j = , , fredSum = fredSum j
In general, the range is begin, [, step].
Another loop construct:
repeat
('the way of the future')
num = num
until num ==
. Functions.
fib(n)
n < return
return fib(n ) fib(n )
Closures and anonymous s are ok:
adder(x)
The returned is created when adder is
called, and remembers the value of x:
return (y) return x y
a = adder()
a = adder()
(a()) >
(a()) >
Returns, func calls, and assignments all work
with lists that may be mismatched in length.
Unmatched receivers are nil;
unmatched sers are discarded.
x, y, z = , , ,
Now x = , y = , z = , and is thrown away.
bar(a, b, c)
(a, b, c)
return , , , , ,
x, y = bar('zaphod') > s "zaphod nil nil"
Now x = , y = , values .. are discarded.
Functions are firstclass, may be localglobal.
These are the same:
f(x) return x x
f = (x) return x x
And so are these:
local g(x) return math.sin(x)
local g; g = (x) return math.sin(x)
the 'local g' decl makes gselfreferences ok.
Trig funcs work in radians, by the way.
Calls with one string param n't need parens:
'hello' Works fine.
. Tables.
Tables = Lua's only compound data structure;
they are associative arrays.
Similar to php arrays or js objects, they are
hashlookup dicts that can also be used as lists.
Using tables as dictionaries maps:
Dict literals have string keys by default:
t = {key = 'value', key = false}
String keys can use jslike t notation:
(t.key) Prints 'value'.
t.newKey = {} Adds a new keyvalue pair.
t.key = nil Removes key from the table.
Literal notation any (nonnil) value as key:
u = {['@!#'] = 'qbert', [{}] = , [.] = 'tau'}
(u[.]) s "tau"
Key matching is basically by value numbers
and strings, but by identity tables.
a = u['@!#'] Now a = 'qbert'.
b = u[{}] We might expect , but it's nil:
b = nil since the lookup fails. It fails
because the key we used is not the same object
as the one used to store the original value. So
strings & numbers are more portable keys.
A onetableparam call needs no parens:
h(x) (x.key)
h{key = 'Sonmi~'} Prints 'Sonmi~'.
key, val in pairs(u) Table iteration.
(key, val)
_G is a special table of all globals.
(_G['_G'] == _G) Prints 'true'.
Using tables as lists arrays:
List literals implicitly set up int keys:
v = {'value', 'value', ., 'gigawatts'}
i = , #v #v is the size of v lists.
(v[i]) Indices start at !! SO CRAZY!
A 'list' is not a real type. v is just a table
with consecutive integer keys, treated as a list.
. Metatables and metamethods.
A table can have a metatable that gives the table
operatoroverloadish behavior. Later we'll see
how metatables support jsprototypey behavior.
f = {a = , b = } Represents the fraction ab.
f = {a = , b = }
This would fail:
s = f f
metafraction = {}
metafraction.__add(f, f)
sum = {}
sum.b = f.b f.b
sum.a = f.a f.b f.a f.b
return sum
setmetatable(f, metafraction)
setmetatable(f, metafraction)
s = f f call __add(f, f) on f's metatable
f, f have no key their metatable, unlike
prototypes in js, so you must retrieve it as in
getmetatable(f). The metatable is a normal table
with keys that Lua knows about, like __add.
But the next line fails since s has no metatable:
t = s s
Classlike patterns given below would fix this.
An __index on a metatable overloads t lookups:
defaultFavs = {animal = 'gru', food = 'nuts'}
myFavs = {food = 'pizza'}
setmetatable(myFavs, {__index = defaultFavs})
eatenBy = myFavs.animal works! thanks, metatable
Direct table lookups that fail will retry using
the metatable's __index value, and this recurses.
An __index value can also be a (tbl, key)
more customized lookups.
Values of __index,add, .. are called metamethods.
Full list. Here a is a table with the metamethod.
__add(a, b) a b
__sub(a, b) a b
__mul(a, b) a b
__div(a, b) a b
__mod(a, b) a % b
__pow(a, b) a ^ b
__unm(a) a
__concat(a, b) a .. b
__len(a) #a
__eq(a, b) a == b
__lt(a, b) a < b
__le(a, b) a <= b
__index(a, b) a.b
__newindex(a, b, c) a.b = c
__call(a, ...) a(...)
. Classlike tables and inheritance.
Classes aren't built in; there are dferent ways
to make them using tables and metatables.
Explanation this example is below it.
Dog = {} .
Dog:new() .
newObj = {sound = 'woof'} .
self.__index = self .
return setmetatable(newObj, self) .
Dog:makeSound() .
('I say ' .. self.sound)
mrDog = Dog:new() .
mrDog:makeSound() 'I say woof' .
. Dog acts like a class; it's really a table.
. tablename:fn(...) is the same as
tablename.fn(self, ...)
The : just adds a first arg called self.
Read & below how self gets its value.
. newObj will be an instance of class Dog.
. self = the class being instantiated. Often
self = Dog, but inheritance can change it.
newObj gets self's s when we set both
newObj's metatable and self's __index to self.
. Reminder: setmetatable returns its first arg.
. The : works as in , but this time we expect
self to be an instance instead of a class.
. Same as Dog.new(Dog), so self = Dog in new().
. Same as mrDog.makeSound(mrDog); self = mrDog.
Inheritance example:
LoudDog = Dog:new() .
LoudDog:makeSound()
s = self.sound .. ' ' .
(s .. s .. s)
seymour = LoudDog:new() .
seymour:makeSound() 'woof woof woof' .
. LoudDog gets Dog's methods and variables.
. self has a 'sound' key from new(), see .
. Same as LoudDog.new(LoudDog), and converted to
Dog.new(LoudDog) as LoudDog has no 'new' key,
but es have __index = Dog on its metatable.
Result: seymour's metatable is LoudDog, and
LoudDog.__index = LoudDog. So seymour.key will
= seymour.key, LoudDog.key, Dog.key, whichever
table is the first with the given key.
. The 'makeSound' key is found in LoudDog; this
is the same as LoudDog.makeSound(seymour).
If needed, a subclass's new() is like the base's:
LoudDog:new()
newObj = {}
set up newObj
self.__index = self
return setmetatable(newObj, self)
. Modules.
[[ I'm commenting out this section so the rest of
this script remains runnable.
Suppose the file mod.lua looks like this:
local M = {}
local sayMyName()
('Hrunkner')
M.sayHello()
('Why hello there')
sayMyName()
return M
Another file can use mod.lua's ality:
local mod = ('mod') Run the file mod.lua.
is the standard way to include modules.
acts like: ( not cached; see below)
local mod = ( ()
)()
It's like mod.lua is a body, so that
locals inside mod.lua are invisible outside it.
This works because mod here = M in mod.lua:
mod.sayHello() Says hello to Hrunkner.
This is wrong; sayMyName only exists in mod.lua:
mod.sayMyName() error
's return values are cached so a file is
run at most once, even when 'd many times.
Suppose mod.lua contains "('Hi!')".
local a = ('mod') Prints Hi!
local b = ('mod') Doesn't ; a=b.
file is like without caching:
file('mod.lua') > Hi!
file('mod.lua') > Hi! (runs it again)
loadfile loads a lua file but esn't run it yet.
f = loadfile('mod.lua') Call f() to run it.
loadstring is loadfile strings.
g = loadstring('()') Returns a .
g() Prints out ; nothing ed bee now.
]]