LUA in a Weekend

Contents: Basics, Flow Control, Functions, Tables

--[[

Typographical Conventions

This is a section

this = code

-- This is a comment  

---> This is program’s output

--You can try/extend the examples (without any setup) here: http://www.lua.org/cgi-bin/demo

--Send me your feedback: noocell@gmail.com

]]

BASICS

Comments

--comments line

--[[

        multiline

comments  (or commented out code block)

]]

Strings

a=”example1”

String Blocks

a=[[This is a

multiline example of a string, which  respects text exactly as written (doesn’t respect escapers like /n .]]

print(a)

--->

This is a

multiline example of a string, which  respects text exactly as written (doesn’t respect escapers like /n .

a=[[print(2)]]                --string blocks also ignore language keywords

print(a)

---> print(2)

Escape Characters

a="First line \nSecond line \n\\ \' \" \n\t after tab "

print(a)

--->

First line

Second line

\ ' "

    after tab

Numbers

a=15

Boolean

a=true

a=false

Nil

-- nil is used to indicate “nothing” and “not existing”

local x                        --variable x has been declared but not initialized

print(x)                      --‘nil’ is returned when a variable has not been initialized  (it holds “nothing”)

---> nil

a=5

a=nil        -- assigning nil deletes a variable (‘a’ will now be collected by Lua's garbage collector)

print(a)     --   (note that we have just deleted a)

print(b)     --   (b does not exist)

--->

nil

nil

Assignment

a = 5

a, b, c = 5, 7, a-1   --Lua supports multiple assignment (if not enough values are given nil is assigned)

     -- Lua first evaluates the values at the right part and then assigns them to left

a, b = b, a              -- easy way to swap values

a, b = func()              -- with multiple assignment you receive multiple returns from a function

                     

Operators

+ - * / ^             (operations)

%                        (modulo A%B = remainder number, after A - whole Bs that can be placed in A. (20%6=2))

==  ~=  >  <  >=  <=    (comparison)    --  ‘~=’ means ‘not equal’  e.g.: if x~=y then...

and  or  not                     (logical)      --    ‘not’ means ‘not true’  e.g.: if not(x>y) then...

=                           (assignment)

#                        (length of a table / string)

..                            (concatenation of strings)      -- e.g.: print(“ena”..”dyo”..3) ---> enadyo3

Precedence

^

not   #     - (unary)

*     /     %

+     -

..

>     <     >=    <=    ~=    ==

and

or

FLOW CLONTROL

Logical Decisions

A and B   --means: if expression A is true then return the result of expression B, else A

A or B           --means: if expression A is true then return the result of expression A, else B

--ternary in Lua

result = (("check expression") and "do if true" or "do if false")

Example:

x=10  y=20

max=(x>y and x or y)                -- equivalent to max= (  ((x>y) and x)  or  y )

                                -- equivalent to max= (  (false  and x) or y )

                                -- equivalent to max=           false or y

                                -- equivalent to max=                         y

print("Max="..max)                ---> Max=20

x=20  y=10

max=(x>y and x or y)                -- equivalent to max= (  ((x>y) and x)  or  y )

                                -- equivalent to max= (  (true and x) or y )

                                -- equivalent to max=            x  or y

                                -- equivalent to max=                 x

print("Max="..max)                ---> Max=20

--Tips:

var = var or value                           -- use or to set default values for missing variables

var = check and act()                        -- use and to call a function only if a check is passed

var = compare and v1 or v2                     -- use and or to get a comparison winner (min, max)

var = check and thistoo() or this()   -- use and or to call both or one of two functions

if statement

if x>y then

  max = x

elseif x<y

  max = y

else

  max = “none”

end

while Loop

--When you don’t know exactly how many iterations you want

while (n <= 10) do

  print(n)

  n = n + 1

end

repeat Loop

--When you don’t know how many iterations you want, but you want code block to run at least once

repeat

  print(n)

  n = n + 1

until n > 10

for Loop (numeric)

--When you know how many iterations you want at max

for n=1,10,1 do

  print(n)

end

Remember here: a)the counter dies outside scope, use additional var to store it for outside

b)don’t alter the counter inside the loop

c)counter,max,step are only calculated once (if they are expressions)

for Loop (generic)

--Use when you want to easily cycle through all the index-value pairs of a table and do something

t = { }

t[1] = 55

t[2] = 105

t.name = "Rick"

for i,v in pairs(t) do                                      -- generic for

  print("element with index: " .. i .. "has value: " .. v )

end

--->    element with index: 1 has value: 55

element with index: 2 has value: 105

element with index: name has value: Rick

-- pairs will give all the elements (with numeric and string indexes)

-- use ipairs instead, to get only the elements with integer indexes

FUNCTIONS

-- a function can take multiple arguments, separated by comma

local function myprinter(a,b,c)

        print(a+b+c)

end

myprinter(2,3,1)

-- if a specific argument is omitted in a function call, it takes the nil value

-- you can prevent errors (e.g. operations with nil) by providing default args values  

local function myprinter(a,b,c)

        a = a or 0

        b = b or 5

        c = c or 1

print(a+b+c)

end

-- a function can return values (one or multiple)

local function calculate(a,b,c)

        sum=a+b+c

        return sum             -- the return keyword must be the last statement in a block

end                             -- tip:if you want to place it above something, enclose it in a ‘do end’ block

add = calculate(2,6,1)

-- to gather all the returned values you must assign appropriate number of reception variables

local function calculate(a,b,c)

        sum=a+b+c

        sub=a-b-c

        return sum, sub

end

add, subtract = calculate(2,6,1)        

print(add.." "..subtract)                ---> 9 -5

--you can also receive all returns with a table constructor

t={calculate(10,1,2)}                --note the { }

print( t[2] )           ---> 7

--sometimes you want to take the values of a table and give them as arguments to a function

--use function unpack(table) to get all table values as individual returns

tt={red={255,0,0},green={0,255,0},blue={0,0,255}}

print( unpack(tt.red) )                        --->    255    0    0

print(  calculate( unpack(tt.green) )  )        --->    255    -255                --Lua is adorable!

local variables

--Local variables only exist in a code block (and the underlying code blocks).

--Local variables can have the same name as a existing global variable. In such cases local variables have --a higher priority than underlying global variables.

counter = 0    -- global variable
function hello()
   local counter     -- override then global count with a local one
   counter = 1       -- modify the local count (higher priority than the global)
end
-- counter is still 0 here

-- you can restrict the scope of local vars inside an artificial code block enclosing code in do code end

-- in Lua, a best practice is to declare a var (local/global) by initializing it (lazily, when needed)

-- local variables are faster to create than globals and get autoreleased (GC) after getting out of scope

-- globals are not garbage collected even if you never use them!


functions as variables

--Functions are also a variable type. The way we did to create functions so far is actually a shortcut to assign a function to a (global) variable:

function calculate()                -- with shortcut
    code...
end

calculate = function()                 -- as variable (the low level way)
   code...
end

--You can pass a function name as an argument to another function

--You can also use functions without a name (e.g. to pass a simple function as an argument)

TABLES

t = {}                         --create an empty table and then populate it...

t[1]=”something”        --you can assign (whatever) values at numeric index positions in the table

t[2]=3

t[“something”]=1        --or at string index positions

t.surname=”LIAN”        --which is the same as “record” positions

--note however that ipairs and #table take into account only integer indexes - no records!

t= {“something”, 3, surname=”LIAN”}                       --you can also populate a table at creation time

print( t[2] )                   --access the table by table[index] to get a value

print( t.surname )        --or with table.record notation to get a value at a string index (record)

t[2]=nil                --delete an entry by assigning nil to its index

table.insert(t,”This value goes at last+1 index”)  --insert an entry at the end of “t” table         

table.insert(t, 3,”This goes at 3rd index”)  --insert an entry at specific index of “t” table

t = { {“hello”, 10}, {15, “hi”} }   --table constructors can be nested

print( t[1][1], t[2][1] )           

---> hello     15

--as said above, you can assign whatever values (variables of any type) at an index (integer/record)

--therefore, you can also assign functions as the value at an index (use record indexing to gain a tag)

t.add = function()

              -- code for addition

       end

--so, you can use tables as function modules (collections) by setting functions in place of record values

mymodule.calculator = function()

                                -- code for calculator

                      end

z = mymodule.calculator(4,1,9)

--recall that functions in Lua are internally created as plain variables of ‘function’ type

myfunc = function()

                --code

         end

--but there is also provided a shortcut for convenient creation

function myfunc()

                --code

end

--similarly, you can have a module function as a record of ‘function’ type

mymodule.calcutor = function()

                        -- code for calculator

                      end

--or use the same shortcut for module functions creation, with “mymodule.” in front of the function name  

function mymodule.calculator()

                          -- code for calculator

end