*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)
}}


トップ   一覧 単語検索 最終更新   ヘルプ   最終更新のRSS