Misc :: Lua (Basic)

Lua

Essentials

Variables

Control

-- if else then
if a < 0 then a = 0 end
if a < b then return a else return b end
if line > MAX then
    line = 0
elseif line < MIN then
    line = MIN
else
    line = 1
end

-- use break to break a loop
while a[i] do
    print(a[i])
end

repeat
    line = io.read()
until line ~=""

-- numerical `for`
-- from exp1 to exp2, with step exp3
-- optional exp3, default 1
-- all three exp would be evaluated only once
--- all three exp were localto the loop
for var = exp1, exp2, exp3 do
    something()
end

-- generic for
-- traverse all values in an iterator

-- goto, use ::name:: for label
-- cannot goto into a block (or a function)
-- cannot jump out of a function
-- cannot jump into the scope of a local var
::s1:: do
    local c = io.read(1)
    if c == '0' then goto s2
    elseif c == nil then print'ok'; return
    else goto s1
    end
end

Numbers

4
0.4
4.57e-3
0.3e12
5E+20

1 == 1.0    -- true
13.0 + 25   -- 28.0

-- Since 5.3, `//` floor division
-- rounds the quotient towards minus infinity
-- both op are int, result in int; otherwise, result in float
3 // 2    -- 1
3.0 // 2    -- 1.0
-9 // 2     -- -5

a % b == a - ((a // b) * b)
math.pi()
math.abs()
math.type()
math.sin()  -- cos, tan, asin etc.
math.max()  -- min

math.random()     -- [0, 1)
math.random(n)  -- int, [1, n]
math.random(x, y)   -- int, [x, y]
math.randomseed()

math.floor() -- ceil, modf
math.modf(3.3)  --> 3, 0.3

math.huge()   -- inf
math.maxinteger
math.mininteger

math.tointeger()

Strings

page = [[
<html>
<body>
Body
</body>
</html>
]]
string.len(s) -- same as `#s`, and s:len()
string.rep(s, n) -- repeat s n times
string.reverse()
string.lower()  -- upper
string.lower(a) < string.lower(b)

string.sub(s, i, j) -- negative counts from end
s = "[in brackets]"
string.sub(s, 2, -2)    -- return chars between []

string.char(97) -- a
string.byte("a")  -- 97
string.char(97, 98, 99) -- abc
string.byte("abc", -1)  -- 99
string.byte(s, 1, -1)   -- list with codes of all chars in s

string.format() -- same as C printf
-- %d for decimal int, %02d zero padding with at least two digits; %2d use  blank for padding
-- %x for hexadecimal
-- %f for floating-point numbers, %.4f
-- %s for string

-- return first and last positions
-- return nil if none found
string.find(s, char)

string.gsub(s, old_char, new_char)

-- use utf8 library
utf8.len("résumé")  -- 6
utf8.char(114, 233, 115, 117, 109, 233)    -- résumé
utf8.codepoint("résumé", 6, 7)  -- 109 233

Tables

a = {}
a["x"] = 10 -- string as index
a.x    -- same as a["x"], but not a[x], only works with string index
a.y     -- nil
a[1] = 20   -- number as index
a[2.0]  -- automatically to a[2]
a[2.1]  -- still a[2.1]

-- when no index is provided, it's automatically starting from 1
a = {x = 10, y = 20, 30, 40}
-- same as a = {["x"] = 10, ["y"] = 20, [1] = 30, [2] = 40}
a[1]    -- 30
a[2]    -- 40

p = {
    color="blue",   -- p.color
    thickness=2,    -- p.thicknes
    {x=0,   y=0},    -- p[1].x = 0
    {x=0,   y=1}     -- p[2]
}
for k, v in pairs(t) do
    print(k, v)
end

for k = 1, #t do
    print(k, t[k])
end
table.insert(t, k, v)

table.insert(t, v)  -- insert at the end
table.remove(t)     -- return the last value

-- move from index f until e (inclusive) to position t
table.move(a, f, e, t)

table.move(a, 1, #a, 2)     -- shift all elements right
a[1] = newElement

table.move(a, 2, #a, 1)     -- shift left
a[#a] = nil     -- need to explicitly erase the last element

-- extra optional para: a table
table.move(a, 1, #a, 1, {}) -- returns a clone
table.move(a, 1, #a, #b + 1, b) -- appends list a to end of b

-- table.unpack takes a list and returns all elements
-- reverse of table.pack
print(table.unpack{10,20,30})    --> 10   20   30
a,b = table.unpack{10,20,30}     -- a=10, b=20, 30 is discarded
print(table.unpack({"Sun", "Mon", "Tue", "Wed"}, 2, 3))     --> Mon    Tue

Functions

print "hello world"     -- print("hello world")
f{x = 10, y = 20}       -- f({x=10, y=20})
function add (a)
    something()
end

-- same as
add = function (a)
    something()
end
function f (a, b) print(a, b) end
f()     --> nil, nil
f(3)    --> 3, nil
f(3, 4, 5)  --> 3, 4

-- variadic
function foo (...)
    local a, b = ...
    print(a, b)
end

-- can have fixed parameter before the dots
function foo (fmt, ...)
    return io.write(string.format(fmt, ...))
end
function foo0 () end                   -- returns no results
function foo1 () return "a" end        -- returns 1 result
function foo2 () return "a", "b" end   -- returns 2 results

function foo0 () end                   -- returns no results
function foo1 () return "a" end        -- returns 1 result
function foo2 () return "a", "b" end   -- returns 2 results

x,y = foo0()      -- x=nil, y=nil
x,y = foo1()      -- x="a", y=nil
x,y,z = foo2()    -- x="a", y="b", z=nil

x,y = foo2(), 20      -- x="a", y=20   ('b' discarded)
x,y = foo0(), 20, 30  -- x=nil, y=20   (30 is discarded)

print(foo0())          -->            (no results)
print(foo1())          --> a
print(foo2())          --> a   b
print(foo2(), 1)       --> a   1
print(foo2() .. "x")   --> ax         (see next)

t = {foo0()}         -- t = {}  (an empty table)
t = {foo1()}         -- t = {"a"}
t = {foo2()}         -- t = {"a", "b"}

t = {foo0(), foo2(), 4}   -- t[1] = nil, t[2] = "a", t[3] = 4

-- use `()` to force only one result returned
print(foo(1))     --> a
print(foo(2))     --> a  b
print(foo(0))     -- (no results)
print(foo(3))     -- (no results)

print((foo0()))        --> nil
print((foo1()))        --> a
print((foo2()))        --> a