Contents

Lua Quickstart

The Lua programming language has similarities to Python syntax, though being much simpler, compact and having less features. This brief intro should help you to start with it immediately (even if you are not Python programmer).

At the same time it is industrial-grade language - you may look at projects Tarantool (difficult to explain what it is but it is cool solution for big enterprises) or Love2D - portable game engine for example.

You can play with it interactively using sandboxes linked below. Here is the main Lua documentation collection - I recommend "Programming in Lua" book and "Reference Manual" for details on functions etc.

Lua Sandbox #1 (compiled to JS) and Lua Sandbox #2 (based on Linux)

Also Lua button is available for execution code from the "solution" box on any task view page. Note that it supports standard Lua 5.4 and LuaJIT 2.1 which is about ten times faster (see below).

To install Lua on your computer visit official Lua download page. PyCharm user may follow this advice from Mathias: after downloading and installing Lua, then install the EmmyLua plugin in PyCharm - that allows you to develop and run Lua programs directly within PyCharm!

Variables and Printing

These are quite similar to Python:

Lua:

x = 5
word = 'Wonder!'
print(word, x)

You'll see however that print makes significant tabulations between elements. Alternative is

io.write(word, x)

it makes no tabulations or spaces between elements, and doesn't append newline (and also returns file value which may confuse in interactive mode).

Another alternative is to concatenate elements to single string (use .. operator):

print(word .. x)

Types and operators

In the example above we've seen that no type conversion is needed when concatenating string to integer. Lua is quite "weak-typed" and converts values back and forth when needed. Look at the following example:

print('100' + 5)        -- gives '105.0'
print('100' .. 5)       -- gives '1005'

You see, with arithmetic addition operator both values are converted to numbers. With concatenation (string addition) operator they both are converted to strings.

Numbers are either integer or float, the latter showing distinctive fractional part (even if it is .0). There are also string values and boolean values (true, false). If value is not initialized it is nil.

Arithmetic operators are +, -, *, / and also // (integer division) along with % (modulo). There are no short forms like a += 1 or a++ for incrementing valriable.

Tables for both lists (arrays) and dicts (maps, hashes)

The only complex type is table, which works at the same time as linear array (list) and dictionary (key-value storage). Slightly unusual feature is indexes normally start with 1 rather than 0 (though one can use 0 anyway):

a = {3, 5, 7}                 -- initializing with curly braces
print(a[2])                   -- prints 5
a[4] = 11                     -- set another value
print(#a)                     -- prints 4, since '#' prefix gets length of array-like table
table.insert(13)              -- slightly clumsy way of appending to array-like table
print(table.concat(a, ':'))   -- prints 3:5:7:11:13

Using tables with non-numeric indexes (keys) works like dealing with dictionary in Python:

a = {john = 15}
print(a['john'], a['jack'])   -- prints "john   nil"
a['jane'] = 18
a['zlobodan'] = {}            -- empty table inserted as table element

Flow control statements

Conditionals if-else and while loops are quite similar to Python, just the internal block is not defined with indentation - rather simply is framed with do .. end words (or then/else .. end):

x = 1
while x < 100 do
    if x % 5 == 0 then
        print('fizz')
    elseif x % 3 == 0 then
        print('buzz')
    end
    x = x + 1
end

There is break statement, but no continue (instead it is possible to use goto).

There are two versions of for loop, the first of them numeric, the other for tables etc:

for i = 1, 10 do
    print(i .. ' squared is ' .. (i * i))
end

for i = 1, 30, 2 do          -- step is 2 instead of 1
    print('odd value', i)
end

a = {2, 3, 5, 7, 11}
for k, v in ipairs(a) do     -- "ipairs" iterates over numeric indexes
    print(k, v)
end

b = {john=15, jake=18, jill = 13}  -- and "pairs" for non-numeric
for k, v in pairs(b) do
    print(k, v)
end

Functions

Quite similar to Python - just define function and use it:

function sqr(x)
    return x * x
end

print(sqr(5))   -- prints 25

Using several values in assignments and returns is allowed (tuple-like behavior)

function intdiv(x, y)
    return x // y, x % y
end

q, r = intdiv(100, 7)

If you use local variables inside function (the same inside if, while etc blocks) it makes sense to mark them with local word, otherwise they are global:

function haha(x)
    t = x * (x + 1) // 2
    local s = x * x
    return t, s
end

haha(15)        -- we ignore returned values for this example
print(t, s)     -- prints "120   nil"

Library functions

There is a typical small set of useful functions in the standard library, most of them are assigned as values to dedicated tables with names like math, string, io:

print(math.sqrt(3*3 + 4*4))    -- square root
print(string.upper('Clown'))   -- prints CLOWN

Refer to reference manual for full list of such "methods". Alternatively it is easy to print out their names, since they are defined via table, e.g.:

for name, func in pairs(math) do
    print(name)
end

There is also behavior allowing to use tables as classes / objects in Python, we won't go into details here, but it is used to shorten popular operations, for example with string:

word = 'abracadabra'
print(string.sub(word, 2, 5))      -- prints substring of "word" from 2 to 5, i.e. "brac"
print(word:sub(2, 5), word:len())  -- does the same, additionally prints length of "word"

Versions

The Lua language comes in several implementations. On this site you can run at least two of them. Standard "scripting" implementation, corresponding to Lua 5.4.6 is executed by default. However if you add any comment with word "luajit" in the first line of your code, LuaJIT 2.1 implementation is used. It is significantly faster (about 10 times), but conforms to language version 5.1 with some features included from 5.2 and 5.3 versions. E.g.

print(_VERSION) -- prints 5.4 normally

but if you add a comment in the first line

--luajit
print(_VERSION) -- prints 5.1, as it is executed by LuaJIT

Try this small program (summing up square roots for values up to million) with both versions and you'll see the difference:

res = 0
for i=1,1000000 do
  res = res + math.sqrt(i)
end
print(res, os.clock())  -- prints time in seconds from the execution start