*Luaで良く作る関数 ~文法編~ [#tfd3313e] -[[enum>#enum]] -[[switch>#switch]] -[[redo, continue, skip (Lua 5.2以上)>#lua52_redo_continue_skip]] -[[continue (Lua 5.1)>#lua51_continue]] -[[continue (Luajit 2.x)>#luajit2_continue]] -[[3項演算子>#ternary_operator]] &aname(enum); **enum [#i4b17115] - enum.luaとして保存 #sh(lua){{ local enum = {} local len_key = "len" local _ = {} setmetatable(_, {__mode = "k"}) function enum:__len() local i = 0 for k, v in pairs(_[self]) do if k ~= len_key then i = i + 1 end end return i end function enum:new(o) local t = {} _[t] = {[len_key] = enum.__len} for k, v in pairs(o) do if tonumber(k) ~= nil then k, v = v, k - 1 end if _[t][k] ~= nil then error('"' .. k .. '" can not be set.', 2) end _[t][k] = v end return setmetatable(t, self) end function enum:__index(k) if _[self][k] == nil then error('"' .. k .. '" is undefined enumerator.', 2) end return _[self][k] end function enum:__newindex() error("enum is read-only.", 2) end return enum }} ~ - 使い方~ test.lua #sh(lua){{ enum = require "enum" test = enum:new{"aa", "bb", cc = 100} print(test.aa) --> 0 print(test.bb) --> 1 print(test.cc) --> 100 print(#test) --> 0 (Lua5.1) or 3 (Lua5.2) print(test:len()) --> 3 --print(test.dd) --> error : "dd" is undefined enumerator. --test.aa = 10 --> error : enum is read-only. }} &aname(switch); **switch [#vbd81dc4] - switch.luaとして保存 #sh(lua){{ function switch(c) local swtbl = { casevar = c, caseof = function (self, code) local f if (self.casevar) then f = code[self.casevar] or code.default else f = code.default end if f then if type(f)=="function" then return f(self.casevar,self) else error("case "..tostring(self.casevar).." not a function") end end end } return swtbl end }} -test.lua #sh(lua){{ require "switch" c = 1 switch(c) : caseof { [1] = function (x) print(x,"one") end, [2] = function (x) print(x,"two") end, [3] = 12345, -- エラー default = function (x) print(x,"default") end, } c = "dde" switch(c) : caseof { ['abc'] = function (x) print(x,"c is abc") end, ['def'] = function (x) print(x,"c is def") end, ['ddd'] = 12345, -- エラー default = function (x) print(x,"default") end, } }} -備考~ switch文の疑似実装について、紹介したものの、実際の所は''if ~ elseif~end''でコツコツと記述した方がメンテナンスしやすい。~ switch文の様々な例:[[http://lua-users.org/wiki/SwitchStatement]] &aname(lua52_redo_continue_skip); **redo, continue, skip (lua 5.2以上) [#i0881982] -Lua 5.2にてgoto文が加わったので、これを上手く利用すれば良い。~ 但し、ラベルは被ることが許されないので、そこが難点である。 #sh(lua){{ ::redo1:: for x=1,10 do for y=1,10 do if not f(x,y) then goto continue1 end if not g(x,y) then goto skip1 end if not h(x,y) then goto redo1 end ::continue1:: end end ::skip1:: ::redo2:: for x=1,10 do for y=1,10 do if not f(x,y) then goto continue2 end if not g(x,y) then goto skip2 end if not h(x,y) then goto redo2 end ::continue2:: end end ::skip2:: }} &aname(lua51_continue); **continue (Lua 5.1) [#i0a1afd2] -Lua 5.1系の場合、Lua本体のC言語ソースの修正が許されるならば、以下のパッチを元にソース自体の修正をするのが良いです。 #ref(http://lua.tips/download/func/grammer/lua5.1.continue.patch) これによって continue文 が使えるようになります。~ &aname(luajit2_continue); **continue (Luajit 2.0) [#i0a1afd2] -Luajit 2.0系の場合、Lua本体のC言語ソースの修正が許されるならば、以下のパッチを元にソース自体の修正をするのが良いです。~ [[Luajit continueの実装>https://github.com/sd-/luajit/commit/612f1797554b5dc3f1d64e4755b3fdc4f11b617a]]~ これによって continue文 が使えるようになります。~ &aname(ternary_operator); **3項演算子 [#u01cb885] -C++の記述 #sh(cpp){{ // C++の3項目演算 x = a ? b : c }} ~ -Luaの記述 #sh(lua){{ -- Luaの3項演算っぽい記述方法 x = a and b or c }} - 例 #sh(lua){{ local cond = 3 local x = cond==3 and "三" or "他" print(x) }}