Dies ist eine alte Version des Dokuments!
Programming in Lua (5.0) Tutorial — Reference Manual — Short Reference — IBM intro: Embeddable scripting with Lua — Linux Journal intro: A Look at Lua
#!/usr/bin/lua
Use global table arg
local inp= io.stdin:read() -- Read a line from stdion print() -- Print a line to stdout io.stdout:write() -- Print a string to stdout io.stderr:write() -- Print a string to stderr
This C code
d= a ? b : c
is in lua:
d= a and b or c
Note that this works only for single assignment. Use auxiliary tables for mulitiple assignment:
d1, d2 = table.unpack(a and {b1, b2} or {c1, c2})
for i = 0,24,4 do -- start, end (including), step print(i) end
Use #
operator
-- Iterate over array part: for i,v in ipairs(now) do print(i,v) end -- Iterate over complete table: for k,v in pairs(now) do print(k,v) end
pairs()
#!/usr/bin/lua -- Numbers: a=3 -- a contains 3 b=a -- b contains 3 a=4 -- a contains 4, b still contains 3 print(a,b) -- 4 3 -- Booleans: a=true; b=a; a=false print(a,b) -- false true -- Strings: a="World" -- a points to the string "World" b=a -- b points to the same string a="Hello" -- a points to "World", b still points to "Hello" print(a,b) --> Hello World -- Functions: a= function() print("World") end b=a -- a and b point to the same function: print(a,b) --> function: 0x80500e8 function: 0x80500e8 a= function() print("Hello") end -- a points to a new function and b still points to the old function: print(a,b) --> function: 0x8050a48 function: 0x80500e8 a() -- Hello b() -- World
#!/usr/bin/lua -- Tables: a={3} b=a; -- a and b point to the same table: print(a,b) -- table: 0x80509e0 table: 0x80509e0 print(a[1],b[1]) -- 3 3 a[1]=4; print(a[1],b[1]) -- 4 4 b[1]=5 print(a[1],b[1]) -- 5 5 a={6} -- a points to a new table and b still points to the old table: print(a,b) -- table: 0x8050a30 table: 0x80509e0 print(a[1],b[1]) -- 6 5 b[1]=7 print(a[1],b[1]) -- 6 7
pcall()
converts an error raising function into an error returning function.
assert()
or similar converts an error returning function into an error raising function.
caller⇓ callee⇒ | return | raise |
---|---|---|
return | check | pcall() + check |
raise | assert() | nothing |
try {…}
-block is done with a function in Lua. That means you end up having one function more for each try/catch usage-- rectangle prototype: rectangle_proto= {species="rectangle"} function rectangle_proto:area() return self.width * self.height end -- rectangle constructor: function new_rectangle(width, height) local rectangle= {width= width, height= height} setmetatable(rectangle, {__index=rectangle_proto}) return rectangle end -- rectangle usage: rectangle= new_rectangle(3,4) print(rectangle:area()) --> 12 print(rectangle.species) --> rectangle -- circle prototype: circle_proto= {species="circle"} function circle_proto:area() return self.radius^2 * math.pi end -- circle constructor: function new_circle(radius) local circle= {radius= radius} setmetatable(circle, {__index=circle_proto}) return circle end circle= new_circle(1) print(circle:area()) --> 3.14 print(circle.species) --> circle
Classic single inheritance chain:
-- Inheritance: shape prototype: shape_proto= {family="shape"} function shape_proto:get_species() return self.species end function shape_proto:get_family() return self.family end setmetatable(rectangle_proto, {__index=shape_proto}) setmetatable(circle_proto, {__index=shape_proto}) print(circle:get_family().."/"..circle:get_species()) --> shape/circle print(rectangle:get_family().."/"..rectangle:get_species()) --> shape/rectangle
Lua print()
does not look for a tostring()
method directly in the table, instead it looks for a method called __tostring()
in its metatable. Thus, to enable both print(myobject:tostring())
(explicit call) and print(myobject)
(implicit call), provide the tostring() method in the prototype table of the object and set __tostring
attribute of the metatable to that method:
-- rectangle prototype: rectangle_proto= {} function rectangle_proto:tostring() return "["..self.width.."|"..self.height.."]" end -- rectangle constructor: function new_rectangle(width, height) rectangle= {width= width, height= height} setmetatable(rectangle, { __index=rectangle_proto, __tostring=rectangle_proto.tostring }) return rectangle end -- rectangle usage: rectangle= new_rectangle(3,4) print(rectangle:tostring()) --> [3|4] print(rectangle) --> [3|4]
This works also if tostring()
is defined in the base clase:
-- shape as base class: shape_proto= {} function shape_proto:tostring() return "["..self.width.."|"..self.height.."]" end -- rectangle prototype inherits from shape: rectangle_proto= {} setmetatable(rectangle_proto, { __index=shape_proto }) -- rectangle constructor: function new_rectangle(width, height) rectangle= {width= width, height= height} setmetatable(rectangle, { __index=rectangle_proto, __tostring=rectangle_proto.tostring }) return rectangle end -- rectangle usage: rectangle= new_rectangle(3,4) print(rectangle:tostring()) --> [3|4] print(rectangle) --> [3|4]
local M= {} local private= {} -- holds private data of all objecs in subtables -- Class Point: -- local Point_proto= {} -- Class prototype function Point_proto:set(x,y) local priv= private[self] priv.x= x priv.y= y end function Point_proto:get() local priv= private[self] return priv.x, priv.y end function Point_proto:tostring() local priv= private[self] return "["..priv.x.."|"..priv.y.."]" end Point_proto.__index = Point_proto Point_proto.__newindex= function() assert(false,"object is write-protected") end setmetatable(Point_proto, { -- ensure read protection for Point and all childs __index= function() assert(false, "object is read-protected") end }) function M.new_Point(x,y) -- constructor local instance= {} setmetatable(instance, Point_proto) private[instance]= {} -- create private part of object instance:set(x,y) return instance end return M
#!/usr/bin/lua local point= require "point" local print_r= function(table) for key,value in pairs(table) do io.write("[", key, "] = ", tostring(value), "\n") end end local p= point.new_Point(3,4) --p.x= 8 --> Write access throws an error --print(p.y) --> Read access throws an error print(p:tostring()) --> [3|4] print_r(p) --> prints nothing
local M= {} local private= {} -- holds private data of all objecs in subtables -- Class Point: -- -- ... -- CLASS MovablePoint: -- local MovablePoint_proto= {} -- Class prototype function MovablePoint_proto:move(dx, dy) local priv= private[self] priv.x= priv.x+dx priv.y= priv.y+dy end MovablePoint_proto.__index = MovablePoint_proto MovablePoint_proto.__newindex= Point_proto.__newindex setmetatable(MovablePoint_proto, Point_proto) -- Inherit from Point function M.new_MovablePoint(x,y) -- constructor local instance= M.new_Point(x,y) -- call parent constructor setmetatable(instance, MovablePoint_proto) return instance end return M
#!/usr/bin/lua local point= require "point" -- ... local mp= point.new_MovablePoint(5,6) mp.x= 9 --> Write access throws an error print(mp.y) --> Read access throws an error print(mp:tostring()) --> [5|6] mp:move(2,1) print(mp:tostring()) --> [7|7] print_r(mp) --> prints nothing
To run some code sitting in a different file, use dofile()
To load global variables of an external (config) file into a table locally, you have to pass the table as environment:
a="Harry" b="Hirsch"
#!/usr/bin/lua local extenv={} local chunk= loadfile("config.lua", "t" , extenv) chunk() for k,v in pairs(extenv) do io.write("[", k, "] = ", tostring(v), "\n") end
[a] = Harry [b] = Hirsch
See ModuleDefinition and LuaStyleGuide → Modules
module()
is deprecated!
now= os.time()
-- Return a table containing hour, min, wday, day, ... of current time: now = os.date("*t") -- Return a table containing hour, min, wday, day, ... of a certain time: atime = os.date("*t", timestamp) -- Return a formated string of current time: now = os.date("Today is %A") -- Today is Thursday
do var= 0 for i=1,102000000 do var= var+1 end end -- real 0m4.516s
do local var= 0 for i=1,102000000 do var= var+1 end end -- real 0m1.003s
local var= 0 do for i=1,102000000 do var= var+1 end end --real 0m0.970s
do local var= 0 local closure= function() for i=1,102000000 do var= var+1 end end closure() end -- real 0m1.666s
do local tab= {var= 0} for i=1,102000000 do tab.var= tab.var+1 end end -- real 0m4.248s
do local tab= {0} for i=1,102000000 do tab[1]= tab[1]+1 end end -- real 0m4.767s
Tested with Lua 5.2
table.concat()
See also:
A newly created coroutine is in state supended
:
co1= coroutine.create(function() end) print(coroutine.status (co1)) --> suspended
A coroutine which resumes another coroutine goes from state running
to normal
while the resumed couroutine goes from state suspended
torunning
:
co1= coroutine.create(function() print("in co1: state main:", coroutine.status(main)) print("in co1: state co1", coroutine.status(co1)) end) main= coroutine.running() -- get handle to main coroutine print("in main: state main:", coroutine.status(main)) print("in main: state co1:", coroutine.status(co1)) coroutine.resume(co1)
Result: in main: state main: running in main: state co1: suspended in co1: state main: normal in co1: state co1 running
A running
couroutine can yield() back to its resumer, which puts the resumer back to running
and itself back to suspended
:
co1= coroutine.create(function() print("in co1: state main:", coroutine.status(main)) print("in co1: state co1", coroutine.status(co1)) coroutine.yield() end) main= coroutine.running() -- get handle to main coroutine coroutine.resume(co1) print("in main: state main:", coroutine.status(main)) print("in main: state co1:", coroutine.status(co1))
Result: in co1: state main: normal in co1: state co1 running in main: state main: running in main: state co1: suspended
Alternatively a running
couroutine can resume another coroutine (which is in state suspended
):
co1= coroutine.create(function() coroutine.resume(co2) end) co2= coroutine.create(function() print("in co2: state main:", coroutine.status(main)) print("in co2: state co1", coroutine.status(co1)) print("in co2: state co2", coroutine.status(co2)) end) main= coroutine.running() -- get handle to main coroutine coroutine.resume(co1)
Result: in co2: state main: normal in co2: state co1 normal in co2: state co2 running
But a running
couroutine cannot resume a non-suspended coroutine. Only coroutines in state suspended
can be resumed:
co1= coroutine.create(function() local res, err= coroutine.resume(main) print(res, err) end) main= coroutine.running() -- get handle to main coroutine coroutine.resume(co1)
Result: false cannot resume non-suspended coroutine
#!/usr/bin/lua co= coroutine.create(function() while true do io.stderr:write('co: waking up\n') local inp= io.stdin:read() io.stderr:write('co: read "'..inp..'", going to sleep\n') coroutine.yield(inp) end end) while true do io.stderr:write('main: going to sleep\n') local state, oup= coroutine.resume(co) io.stderr:write('main: waking up\n') print('> '..oup) end