00:00
Crash Course Lua

vrld @ GPN12

About me

Wo Lua?

Warum Lua?

Variablen und Typen

Variablen

Zuweisung

Werte und Typen

nil

boolean

number

string

string \(\Leftrightarrow\) number

table

table erstellen

t = {}
t[1] = 'foo'
t['bar'] = 1
t.baz = {}
t[t] = t
print(t[1]) --> foo

t[1] = nil
print(t[1]) --> nil

s = { 'foo', 2, 3,
	['bar'] = 1;
	baz     = {};
	[s]     = s, --< Fehler! s = nil
}
print(s[2], s.baz) --> 2    table: 0x19f6570

table als Array

tables sind Objekte

function

Mehr

Kontrollstrukturen

if then else

if a < 0 then a = 0 end

if op == '+' then
    print(a+b)
elseif op == '-' then
    print(a-b)
elseif op == '*' then
    print(a*b)
elseif op == '/' then
    print(a/b)
else
    error("Invalid operation: " .. op)
end

case?

while und repeat

Numerisches for

Generisches for

break und return

Lokale Variablen

Funktionen

Zucker

Higher Order Functions

Mehrere Rückgabewerte

Variadische Funktionen

Variadische Funktionen II

Signal/Slots

reg = {}
function emit(s, ...)
	for f in pairs(reg[s] or {}) do f(...) end
end

function register(s, f)
	if not reg[s] then reg[s] = {} end
	reg[s][f] = f
	return f
end

function remove(s,f) (reg[s] or {})[f] = nil end

f = register('foo', function(a) print('f:', a) end)
g = register('foo', function(a) print('g:', a) end)
emit('foo', 'bar') --> f:   bar; g:   bar

Closures

case!

function case(x)
	return function(t)
		local c = t[x or 'default'] or t.default
		return type(c) == "function" and c() or c
	end
end

foo = 1
bar = case (foo) {
	[1] = 'foo';
	[2] = 'bar';
}
case (bar) {
	bar     = function() print('bar') end;
	default = function() print('default') end
} --> default

Kapselung

Funktionen überschreiben

Iterators/Generators

Generisches for

Zustandslose Generatoren

Coroutine Basics

co = coroutine.create(function()
	for i = 1,10 do coroutine.yield(i) end
end)

print(coroutine.status(co)) --> suspended
repeat
	local ok, i = coroutine.resume(co)
	print(i) --> 1; 2; ...; 10; nil
until i == nil
print(coroutine.status(co)) --> dead
print(coroutine.resume(co))
				--> false   cannot resume dead coroutine

Abkürzung

f = coroutine.wrap(function()
	for i = 1,10 do coroutine.yield(i) end
end)

repeat
	local v = f()
	print(v) --> 1; 2; ...; 10; nil
until v == nil

f() --> stdin:1: cannot resume dead coroutine
    --> stack traceback:
    -->      [C]: in functionion 'f'
    -->      stdin:1: in main chunk
    -->      [C]: ?

Coroutine als Generator

function words(path)
	return coroutine.wrap(function()
		for line in io.lines(path) do
			for w in line:gmatch('%w+') do
				coroutine.yield(w)
			end
		end
	end)
end

for w in words('index.html') do
	print(w) --> DOCTYPE; html; html; head; meta; ...
end

Metatables

Metatable Basics

Metamethoden

Arithmetik cont.

function complex.__mul(x,y)
	local a,b, c,d = x[1],x[2], y[1],y[2]
	return complex.new(a*c - b*d, a*d + b*c)
end

function complex.__div(x,y)
	local a,b, c,d = x[1],x[2], y[1],y[2]
	local re = (a*c + b*d)/(c*c + d*d)
	local im = (b*c - a*d)/(c*c + d*d)
	return complex.new(re, im)
end

a,b = complex.new(1,2), complex.new(3,4)
c,d,e =  a+b, a*b, a/b

Relationen

function complex.__eq(x,y)
	return x[1] == y[1] and x[2] == y[2]
end

function complex.__le(a,b)
	return x[1] < y[1] and x[2] <= y[2]
end

function complex.__lt(a,b)
	local a,b,c,d = x[1],x[2], y[1],y[2]
	return a < c or (a == c and b <= d)
end

tostring() & friend

function complex.__tostring(a)
	return "(" .. a[1] .. " + " .. a[2] .. "i)"
end

function complex.__concat(a,b)
	return tostring(a) .. tostring(b)
end

print(complex.new(2,3)) --> (2 + 3i)
s = "answer = " .. complex.new(4,2)
print(s)                --> answer = (4 + 2i)

__index und __newindex

function complex.__index(x, k)
	return ({re = x[1], im = x[2]})[k]
end

function complex.__newindex(x, k, v)
	local i = ({re = 1, im = 2})[k]
	x[i] = v
end

c = complex.new(math.pi, -1)
print(c.re, c.im) --> 3.14159...   -1

c.re, c.im = 3, 1
print(c.re, c.im) --> 3    1

Lazy Loading

images = setmetatable({}, {__index = function(_, p)
	p = "images/" .. p .. ".png"
	print("loading", p)
	local img = assert(loadImage(p))
	images[path] = img
	return img
end})

draw(images.troll) --> loading   images/troll.png
draw(images.troll) --> <nix>

Read-Only Tables

function readOnly(t)
	return setmetatable(t, {__newindex = function(_,k)
		error("Cannot create field " .. k)
	end})
end

t = readOnly{
	foo = 1,
	bar = 2
}
t.foo = 2
t.baz = 3 --> stdin:1: Cannot create field baz

Dinge, für die keine Zeit mehr ist

The End