LUA Notes

Page Contents

Comments

--Comment
--[[
This is a multi
line comment
]]

Configure LUA To Use 32-bit Numbers!

See LUA_32BITS in file luaconf.h

Command Line Options

% lua -i prog run chunk then interaction

Or use dofile(<filename>)

The -e option allows us to enter code directly into the command line, like here:

 % lua -e "print(math.sin(12))"

The -l option loads a library. A

Globals

Global variables do not need declarations; we simply use them

Conditionals

DIFFERENT FROM C-LIKE LANGUAGES: Conditional tests (e.g., conditions in control structures) consider both the Boolean false and nil as false and anything else as true. In particular, Lua considers both zero and the empty string as true in conditional tests.

Flow Control

Ifs

if op == "+" then
    r = a + b
elseif op == "-" then
    r = a - b
else
    error("invalid operation")
end

While

local i = 1
while a[i] do
    print(a[i])
    i = i + 1
end

Repeat

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

For

Numerical:

for var=start_exp,stop_exp,step_exp do
   something
end

Generic:

t = {10, print, x = 12, k = "hi"}
for k, v in pairs(t) do --< order that elements appear in a traversal is undefined.
   print(k, v)
end

Strings

Strings in Lua are immutable values. We cannot change a character inside a string, as we can in C;

We can get the length of a string using the length operator (denoted by #):

 a = "hello"
 print(#a) --> 5
 print(#"good bye") --> 8

Concat with ..:

> "Hello " .. "World" --> Hello World
> "result is " .. 3 --> result is 3

Long string literals:

longtext = [==[
            ^^
            Can add zero or more equals between brackets if we need to write a = b[c[1]], for example 
blah
blah
==]]

String library string.len(s) === #s

Tables

Only data structuring mechanism. They represent arrays, sets, records, and many other data structures. Just an associative array.

> a = {} -- create a table and assign its reference
> b = a -- 'b' refers to the same table as 'a'

Table fields evaluate to nil when not initialized.

a.name is syntactic sugar for a["name"]

Constructing Tables

Tables As Lists

Indexing is 1 based not 0 based!!!

days = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"}
print(days[1]) --> Sunday

Record Style (Kinda Like A Struct)

a = {x = 10, y = 20}
-- Equivalent to
-- a = {}; a.x = 10; a.y = 20

Mix List and Record Style

polyline = {color="blue",
   thickness=2,
   npoints=4,
   {x=0, y=0},   -- polyline[1]
   {x=-10, y=0}, -- polyline[2]
   {x=-10, y=1}, -- polyline[3]
   {x=0, y=1}    -- polyline[4]
}

Square Bracket Init

opnames = {["+"] = "add", ["-"] = "sub",
 ["*"] = "mul", ["/"] = "div"}

 i = 20; s = "-"
 a = {[i+0] = s, [i+1] = s..s, [i+2] = s..s..s}

 print(opnames[s]) --> sub
 print(a[22]) --> ---

Traversal

Use pairs iterator:

t = {10, print, x = 12, k = "hi"}
for k, v in pairs(t) do --< order that elements appear in a traversal is undefined.
   print(k, v)
end

Or for lists use ipairs() to ensure traversal order.

Table Library

Functions to operate over lists and sequences.

Functions

function functionName(param1, param2, )
    return 1
end

Can call function with less params than defined with - those params are nil.

Functions can return multiple results:

    return 1,2,3

Function called as a statement - all returned results dropped Function called as an expression - only the first result returned kept Function is last or only expression in list of expressions - All results kept

C API

Object Orientism Through Prototypical Inheritance

If a variable or function does not exist in the type then lookup the thing in the metatable.

The general pattern is this:

// In this example the thing being created is a blob of user data, which is pushed onto the stack.
my_user_data = lua_newuserdatauv(L, my_user_data_size, num_user_data_slots); 
// Stack = [UD]

// Next the metatable associated with the type of thing is pushed onto the top of the stack.
luaL_getmetatable(L, "type-of-thing");
// Stack = [UD, MT]

// Duplicate the top of the stack and push it onto the stack - in this case duplicates MT.
lua_pushvalue(L, -1);
// Stack = [UD, MT, MT]

// Set MT.__index = MT. This tells Lua that if it can't find a field in the thing, look for it in the thing's metatable.
// The setfield function sets "__index" to whatever is on the top of the stack, in this case the MT. It then pops the 
// value off stack.
lua_setfield(L, -1, "__index");        
// Stack = [UD, MT]

// Associate the metatable with the thing. Set UD.__metatable = MT. Pop value off stack. 
lua_setmetatable(L, -2);                        
// Stack [UD]

The way lookup works is that if the member being looked up in the thing is not found, Lua looks for an associated meta table. If it finds that it then looks it up in the meta table.

Thus by putting values and functions in the meta table, and associating it with that type, the type "inherits" those things from the meta table.

To put functions etc in the meta table, the following pattern can be used:

static const luaL_Reg METHOD_FUNCS[] = {
        {"func_name_1",  func_name_1},
        // ...
        {NULL, NULL}
};

// create metatable containing buffer object methods
luaL_newmetatable(L, APP_LUA_BUFFER_METATABLE);
// Stack = [..., MT]

// Add the functions in METHOD_FUNCS to the metatable object
luaL_setfuncs(L, METHOD_FUNCS, 0);
// Stack = [..., MT]

// Pop the MT off the stack to retore the stacks state
lua_pop(L, 1);
// Stack = [...]