前一段时间在看《Programming in Lua, 2Nd Edition》,纪录了一些代码:
local function languageTest() -- table test local names = {"Peter", "Paul", "Mary"} local grades = {Mary=10, Paul=7, Peter=8} table.sort(names, function(n1, n2) return grades[n1] > grades[n2] end) for i=1, #names do print(names[i]) end -- function test local function newCounter(name) local i = 0 return function() i = i+1 return name .. ":" .. i end end local c1 = newCounter("c1") local c2 = newCounter("c2") print(c1()) print(c1()) print(c2()) print(c1()) print(c2()) -- for test local function values(t) local i = 0; return function() i=i+1; return t[i] end end for elm in values(names) do print(elm) end -- -- for test2 -- for k in pairs(names) do -- print(k) -- end end local function tableTest() local Set = {} local mt = {} -- create a new set with teh values of the given list Set.new = function(l) local set = {} setmetatable(set, mt) for _, v in ipairs(l) do set[v] = true end return set; end Set.union = function(a, b) if getmetatable(a) ~= mt or getmetatable(b) ~= mt then error("attempt to 'add' a set with a non-set value", 2); end local res = Set.new {} for k in pairs(a) do res[k] = true end for k in pairs(b) do res[k] = true end return res end Set.intersection = function(a, b) local res = Set.new {} for k in pairs(a) do res[k] = b[k] end return res end Set.tostring = function(set) local l = {} for e in pairs(set) do l[#l+1] = e end return "{" .. table.concat(l, ", ") .. "}" end Set.print = function(s) print(Set.tostring(s)) end mt.__add = Set.union mt.__mul = Set.intersection mt.__tostring = Set.tostring mt.__le = function(a, b) for k in pairs(a) do if not b[k] then return false end end return true end mt.__lt = function(a, b) return a<=b and not (b<=a) end mt.__eq = function(a, b) return a<=b and b<=a end local s1 = Set.new {10, 20, 30, 50} local s2 = Set.new {30, 1} local s3 = s1+s2+s2 -- local s3 = s1+s2+s2 + 8 Set.print(s3) Set.print((s1+s2)*s1) s1 = Set.new{2, 4} s2 = Set.new{4, 10, 2} print(s1<=s2) print(s1<s2) print(s1>=s2) print(s1>s2) print(s1==s2*s1) s1 = Set.new {10, 4, 5} print(s1) -- mt.__metatable = "not your business" -- print(getmetatable(s1)) -- setmetatable(s1, {}) local Window = {} -- create a namespace --create teh prototype with default values. Window.prototype = {x=0, y=0, width=100, height=100} Window.mt = {} -- create a metatable --declare the constructor function function Window.new(o) setmetatable(o, Window.mt) return o end Window.mt.__index = function(table, key) return Window.prototype[key] end -- Window.mt.__index = Window.prototype w = Window.new {x=10, y=20} print(w.x) -- Tables with default values local function setDefault(t, d) local mt = {__index = function() return d end} setmetatable(t, mt) end local tab = {x=10, y=20} print(tab.x, tab.z) setDefault(tab, 0) print(tab.x, tab.z) local mt = {__index = function(t) return t.___ end } local function setDefault(t, d) t.___ = d setmetatable(t, mt) end -- Tracking table accesses local t = {} -- original table (created somewhere) -- keep a private access to the original table local _t = t -- create proxy t = {} -- create metatable local mt = { __index = function(t, k) print("*access to element " .. tostring(k)) return _t[k] end, __newindex = function(t, k, v) print("*update of element " .. tostring(k) .. " to " .. tostring(v)) _t[k] = v -- update original table end } setmetatable(t, mt) t[2] = "hello" print(t[2]) -- Read-only tables function readOnly(t) local proxy = {} local mt = { __index = t, __newindex = function(t, k, v) error("attempt to update a read-only table", 2) end } setmetatable(proxy, mt) return proxy end days = readOnly {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"} print(days[1]) -- days[2] = "Noday" end local function objectTest() local Account = { balance = 0, new = function(self, o) o = o or {} -- create table is user does not provide one setmetatable(o, self) self.__index = self return o end, withdraw = function(self, v) if v>self.balance then error"insufficient funds" end self.balance = self.balance - v end, deposit = function(self, v) self.balance = self.balance + v end } local a = Account:new {balance = 0} a:deposit(100.00) print(a.balance) local b = Account:new() print(b.balance) b.balance = 123 print(b.balance) b:withdraw(100) print(b.balance) print(a.balance) -- inheritance local SpecialAccount = Account:new({ withdraw = function(self, v) if v - self.balance >= self:getLimit() then error"insufficient funds" end self.balance = self.balance - v end, getLimit = function(self) return self.limit or 0 end }) local s = SpecialAccount:new {limit=1000.00} s:deposit(100.00) s:withdraw(200.00) print("s:", s.balance) end local function main() languageTest(); tableTest(); objectTest(); end main()