- 追加された行はこの色です。
- 削除された行はこの色です。
*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)
}}