基礎
Hello World
printは自動的に改行を追加
-- comments start with --
print("Hello, World!")
-- variables (global by default)
x = 10
name = "Alice"
-- local variables
local y = 20
local z = x + y
-- multiple assignment
local a, b, c = 1, 2, 3
print(a, b, c) -- 1 2 3コメント
--[[ ]]は複数行コメント用
-- single line comment
--[[ multi-line
comment block ]]
print("hi")
-- long-bracket comments can have = signs for nesting
--[==[ this is a comment with ]] inside ]==]
print("still runs")オプションのセミコロン
セミコロンは省略可能
print("Hello") -- prints with a trailing newline
io.write("no newline") -- writes without a newline
-- print separates multiple args with tabs
print("name", "age") -- name age
-- print converts all types (nil included)
print(42, true, nil) -- 42 true nil
-- io.stdout / io.stderr are file handles
io.stderr:write("warning\n")多重代入
複数変数へ同時代入をサポート
local a, b = 1, 2
print(a, b) -- 1 2
a, b = b, a -- swap without a temp variable
print(a, b) -- 2 1
local x, y, z = 10 -- y, z become nil
local m, n = 1, 2, 3 -- 3 is discarded
print(m, n) -- 1 2対話モード
lua -iで対話モードに入る
-- run the REPL: lua -i
-- run a file: lua script.lua
-- show the version: lua -v
-- inside the REPL:
-- > print("hi")
-- hi
-- > = 2 + 3 -- '=' prints an expression value
-- 5
-- > = string.rep("ab", 3)
-- abababnil & Variable Deletion
nil is Lua's only 'no value' type. Assigning nil to a table key deletes it. Accessing undeclared globals returns nil rather than raising an error, which can mask typos—use strict.lua to catch them.
local x = 10
print(x) -- 10
x = nil -- delete the value
print(x) -- nil
if x == nil then
print("x is nil")
end
-- reading an undeclared name returns nil (no error)
print(undefined_var) -- nil
-- assign nil to let the GC collect a table entry
local t = {a = 1}
t.a = nil変数
local変数
localはローカル変数を宣言
-- Lua has 8 basic types:
print(type(nil)) -- nil
print(type(true)) -- boolean
print(type(42)) -- number
print(type("hi")) -- string
print(type({})) -- table
print(type(print)) -- function
print(type(coroutine.create(function() end))) -- thread
print(type(io.stdin)) -- userdata
-- type() always returns a string
print(type(type(42))) -- stringグローバル変数
localがない場合、グローバル変数になります
-- Lua 5.3+ distinguishes integers and floats
local i = 10 -- integer
local f = 3.14 -- float
print(type(i), math.type(i)) -- number integer
print(type(f), math.type(f)) -- number float
local hex = 0xFF -- 255
local exp = 1e3 -- 1000.0 (float)
print(hex, exp)
-- integer / integer with no fraction stays integer
print(7 / 2) -- 3.5 (true division, always float)
print(7 // 2) -- 3 (floor division)多重代入
足りない値はnilになり、余分な値は破棄されます
local s1 = "double quoted"
local s2 = 'single quoted' -- identical to double
local s3 = [[
a multi-line
string, escapes ignored]]
print(#s1) -- 14 (# is the length operator)
print(s1:upper()) -- DOUBLE QUOTED
-- strings are immutable: operations return new strings変数のスワップ
一時変数不要
local flag = true
local done = false
-- ONLY nil and false are falsy
-- 0, "", and {} are all truthy (unlike many languages)
if 0 then print("0 is truthy") end
if "" then print("empty string is truthy") end
-- logical operators short-circuit and return a value
local x = nil or "default" -- "default"
local y = true and "yes" -- "yes"
print(x, y)変 数の削除
nilを代入するとGCが回収
-- the table is Lua's only composite data structure
-- it serves as array, dictionary, object, and module
local arr = {10, 20, 30} -- array (1-indexed)
local dict = {name = "Lua", ver = 5.4}
local mixed = {1, 2, x = 3}
print(arr[1]) -- 10 (indices start at 1, not 0)
print(dict.name) -- Lua
print(mixed.x) -- 3
print(#arr) -- 3Type Checks
type() is the standard way to branch on a value's type. It returns 'nil' for nil rather than erroring. For finer checks use math.type (int vs float) or rawequal for identity comparison.
local function describe(v)
local t = type(v)
if t == "table" then
return "a table"
elseif t == "string" then
return "a string: " .. v
elseif t == "nil" then
return "nothing"
end
return "a " .. t
end
print(describe({})) -- a table
print(describe("hi")) -- a string: hi
print(describe(nil)) -- nothingデータ型
基本型
Luaには8つの基本型があります
print(10 + 3) -- 13
print(10 - 3) -- 7
print(10 * 3) -- 30
print(10 / 3) -- 3.3333... (true division)
print(10 % 3) -- 1 (modulo)
print(2 ^ 10) -- 1024.0 (^ is exponent, NOT xor)
print(-5) -- -5 (unary minus)数値
Lua 5.3+は整数と浮動小数点数を区別
-- Lua 5.3+ integer floor division
print(10 // 3) -- 3 (integer)
print(-10 // 3) -- -4 (floors toward -inf)
print(10.0 // 3) -- 3.0 (float floor div)
-- modulo result takes the sign of the divisor
print(10 % 3) -- 1
print(-10 % 3) -- 2
print(10 % -3) -- -2文字列
#で文字列長を取得
print(3 == 3) -- true (equality)
print(3 ~= 4) -- true (inequality: ~=, not !=)
print(3 < 4) -- true
print(3 > 4) -- false
print(3 <= 3) -- true
print(3 >= 4) -- false
print("abc" < "abd") -- true (lexicographic)
print(1 == "1") -- false (different types never equal)ブール値
0と空文字列は真として扱われます
-- and / or / not short-circuit and return a value (not a bool)
print(true and 10) -- 10
print(false or "x") -- "x"
print(nil or "default") -- "default"
print(not nil) -- true
-- idiom for defaults
local name = nil
local display = name or "anonymous"
-- ternary-like (beware falsy 'false' values!)
local v = (cond) and "yes" or "no"テーブル
tableは唯一の複合データ構造です
local name = "Lua"
local v = 5.4
print("Hello " .. name .. " " .. v) -- Hello Lua 5.4
-- .. always creates a new string
local s = "a" .. "b" .. "c"
print(s) -- abc
-- numbers are auto-converted when concatenated
print("n=" .. 42) -- n=42
-- repeat a string with string.rep
print(string.rep("ab", 3)) -- abababLength Operator
# returns the byte length of a string or the length of a table's sequence part. It is only well-defined for tables without holes (nil gaps). For UTF-8 character counts use lua-utf8 or the utf8 library (Lua 5.3+).
-- # works on strings and the sequence part of tables
print(#"hello") -- 5
print(#{10, 20, 30}) -- 3
-- caution: # only counts the contiguous sequence part
-- the result is UNDEFINED if the table has holes
local t = {1, 2, nil, 4}
print(#t) -- 2 or 4 (implementation-defined)
-- # on a string returns its byte length, not codepoints
print(#"cafe") -- 4
print(#"café") -- 5 (é is 2 bytes in UTF-8)演算子
算術演算子
^はべき乗で、XORではありません
local score = 85
if score >= 90 then
print("A")
elseif score >= 80 then
print("B")
elseif score >= 70 then
print("C")
else
print("F")
end
-- keywords: if / then / elseif / else / end
-- parentheses around the condition are optional切り下げ除算
//は切り下げ除算です
local i = 1
while i <= 5 do
print(i)
i = i + 1 -- Lua has no ++ operator
end
-- the condition is checked before each iteration
local n = 0
while n < 3 do
print("loop", n)
n = n + 1
end比較演算子
~=は等しくないを意味します
-- repeat-until runs the body at least once (like do-while)
-- the loop STOPS when the condition becomes true
local i = 1
repeat
print(i)
i = i + 1
until i > 5
-- the condition can see locals declared in the body
local x
repeat
x = math.random(1, 10)
until x == 7論理演算子
and/orは短絡評価をサポート
-- for start, stop[, step]
for i = 1, 5 do
print(i) -- 1 2 3 4 5
end
for i = 10, 1, -2 do
print(i) -- 10 8 6 4 2
end
-- step defaults to 1; the loop variable is local to the loop
for i = 1, 3 do print(i) end
-- print(i) -- i is out of scope here文字列連結
..は文字列を連結
local arr = {"a", "b", "c"}
-- ipairs iterates the array (sequence) part, 1..n
for i, v in ipairs(arr) do
print(i, v) -- 1 a / 2 b / 3 c
end
local dict = {x = 1, y = 2}
-- pairs iterates ALL key/value pairs (order not guaranteed)
for k, v in pairs(dict) do
print(k, v)
end長さ演算子
#は文字列またはテーブルの長さを取得
-- break exits the innermost loop only
for i = 1, 10 do
if i == 5 then break end
print(i) -- 1 2 3 4
end
-- Lua has NO continue; emulate it with goto
for i = 1, 5 do
if i % 2 == 0 then goto continue end
print(i) -- 1 3 5
::continue::
end
-- goto jumps to a label ::name:: within the same scope制御フロー
if-elseif-else
thenとendキーワードに注意
local s1 = "double 'quoted'"
local s2 = 'single "quoted"'
local s3 = "line1\nline2\ttabbed"
local s4 = "percent: %d %%"
-- long brackets: escapes are NOT processed
local s5 = [[raw \n string, \t kept literal]]
print(s3, s5)whileループ
while-do-end
local s = "hello"
print(#s) -- 5 (byte length)
-- the string library is 1-indexed
print(s:sub(1, 3)) -- "hel"
print(s:sub(-2)) -- "lo" (negative = from end)
print(s:byte(1)) -- 104 (ASCII of 'h')
print(string.char(104, 105)) -- "hi"repeat-until
do-whileに似ています、条件が真のとき終了
-- [[ ]] preserves newlines exactly
local text = [[Line 1
Line 2
Line 3]]
print(text)
-- match bracket level to allow ]] inside
local code = [==[
if a then ]] -- this ]] is literal
end ]==]
print(code)数値for
for 開始, 終了, ステップ
local n = tonumber("42") -- 42 (number)
local f = tonumber("3.14") -- 3.14
local bad = tonumber("abc") -- nil (no error raised)
local s = tostring(42) -- "42"
local b = tostring(true) -- "true"
local nil_s = tostring(nil) -- "nil"
print(tonumber("0x1F")) -- 31 (hex)
print(tonumber("11", 2)) -- 3 (base 2)汎用for
ipairsは配列を反復、pairsはすべてを反復
-- string.format uses C-style format strings
print(string.format("%d + %d = %d", 2, 3, 5)) -- 2 + 3 = 5
print(string.format("%.2f", 3.14159)) -- 3.14
print(string.format("%5d", 42)) -- " 42"
print(string.format("%-10s|", "hi")) -- "hi |"
print(string.format("%x %o", 255, 8)) -- ff 10break
Luaにはcontinueがありません
local s = "Hello, World"
-- s:method(x) is sugar for string.method(s, x)
print(s:upper()) -- HELLO, WORLD
print(s:lower()) -- hello, world
print(s:rep(2)) -- Hello, WorldHello, World
print(s:reverse()) -- dlroW ,olleH
print(s:sub(1, 5)) -- Hello
print(s:find("World")) -- 8 13 (start and end indices)関数
関数定義
local functionはローカル関数を定義
-- array (sequence)
local arr = {10, 20, 30, 40}
-- dictionary (hash)
local p = {name = "Lua", version = 5.4}
-- mixed: both sequence and hash entries
local m = {1, 2, 3, lang = "Lua"}
print(arr[1]) -- 10 (1-indexed!)
print(p.name) -- Lua
print(p["version"]) -- 5.4
print(#arr) -- 4複数戻り値
関数は複数の値を返せます
local t = {name = "Lua", ["full name"] = "Lua 5.4"}
-- dot notation works only for valid identifiers
print(t.name) -- Lua
-- bracket notation works for any string key
print(t["full name"]) -- Lua 5.4
-- bracket form accepts variables
local key = "name"
print(t[key]) -- Lua
t.name = "LuaLang"
t["new key"] = 99可変長引数関数
...は可変長引数を表します
local t = {10, 20, 30}
table.insert(t, 40) -- append: {10,20,30,40}
table.insert(t, 1, 5) -- insert at index 1: {5,10,20,30,40}
print(#t) -- 5
local removed = table.remove(t) -- pop last: 40
local first = table.remove(t, 1) -- remove index 1: 5
print(removed, first, #t) -- 40 5 3
-- table.move(src, f, e, t[, dst]) (Lua 5.3+)
local src = {1, 2, 3, 4, 5}
table.move(src, 2, 4, 1) -- copy elements 2..4 to position 1匿名関数
関数は第一級オブジェクトです
local nums = {5, 2, 8, 1, 9}
table.sort(nums)
print(table.concat(nums, ",")) -- 1,2,5,8,9
-- custom comparator (return true if a should come before b)
local people = {
{name = "Bob", age = 30},
{name = "Ann", age = 25},
}
table.sort(people, function(a, b) return a.age < b.age end)
for _, p in ipairs(people) do print(p.name, p.age) end
-- Ann 25 / Bob 30引数としての関数
高階関数
local t = {10, 20, 30, name = "Lua"}
-- ipairs: sequence part, stops at the first nil
for i, v in ipairs(t) do
print(i, v) -- 1 10 / 2 20 / 3 30
end
-- pairs: every key/value pair (order not guaranteed)
for k, v in pairs(t) do
print(k, v) -- includes name Lua (order varies)
end
-- numeric loop over the sequence
for i = 1, #t do print(t[i]) endTable Length & Nested Tables
Tables nest naturally—matrix[r][c] indexes a row then a column. # on a nested table gives that row's length. table.concat efficiently joins a sequence of strings (and numbers) with a separator.
local matrix = {
{1, 2, 3},
{4, 5, 6},
{7, 8, 9},
}
print(matrix[2][3]) -- 6 (row 2, col 3)
print(#matrix) -- 3 (number of rows)
print(#matrix[1]) -- 3 (number of cols)
-- table.concat joins an array of strings/numbers
print(table.concat({"a", "b", "c"}, "-")) -- a-b-c
print(table.concat({1, 2, 3}, "")) -- 123テーブル
テーブルの作成
テーブルは配列と辞書として使用できます
-- named (global) function
function greet(name)
return "Hello, " .. name
end
-- local function (preferred)
local function add(a, b)
return a + b
end
print(greet("Lua")) -- Hello, Lua
print(add(2, 3)) -- 5
-- functions are first-class values
local f = add
print(f(10, 20)) -- 30要素へのアクセス
2つのアクセス方法: .と[]
local function minmax(arr)
local lo, hi = arr[1], arr[1]
for _, v in ipairs(arr) do
if v < lo then lo = v end
if v > hi then hi = v end
end
return lo, hi
end
local mn, mx = minmax({3, 1, 4, 1, 5})
print(mn, mx) -- 1 5
-- values are adjusted: extras dropped, missing become nil
local a = minmax({2, 7}) -- a = 2 (mx discarded)配列操作
tableライブラリが配列操作を提供
local function sum(...)
local total = 0
for _, v in ipairs({...}) do
total = total + v
end
return total
end
print(sum(1, 2, 3, 4)) -- 10
-- select('#', ...) = count; select(n, ...) = args from n
local function info(...)
print(select("#", ...)) -- number of args
print(select(2, ...)) -- args from position 2 onward
endソート
カスタム比較関数をサポート
-- functions are first-class: assign to a variable
local double = function(x) return x * 2 end
print(double(21)) -- 42
-- as table fields
local ops = {
add = function(a, b) return a + b end,
mul = function(a, b) return a * b end,
}
print(ops.add(2, 3), ops.mul(2, 3)) -- 5 6
-- passed inline to higher-order functions
table.sort({3, 1, 2}, function(a, b) return a > b end)反復
ipairsは配列部分を反復
local function map(arr, fn)
local result = {}
for i, v in ipairs(arr) do
result[i] = fn(v)
end
return result
end
local doubled = map({1, 2, 3}, function(x) return x * 2 end)
print(table.concat(doubled, ",")) -- 2,4,6
local function filter(arr, pred)
local out = {}
for _, v in ipairs(arr) do
if pred(v) then out[#out + 1] = v end
end
return out
endテーブル長
#は連続した配列にのみ機能
-- Lua has no native named args; pass a table instead
local function create(opts)
opts = opts or {}
local name = opts.name or "anonymous"
local age = opts.age or 0
return {name = name, age = age}
end
-- call f{...} is sugar for f({...})
local p = create{name = "Alice", age = 30}
print(p.name, p.age) -- Alice 30メタテーブル
メタテーブルの設定
__indexはルックアップ動作を定義
local function make_counter()
local count = 0
return function()
count = count + 1
return count
end
end
local c = make_counter()
print(c()) -- 1
print(c()) -- 2
print(c()) -- 3
-- the inner function captures 'count' (an upvalue)演算子オーバーロード
+ - * / == <などの演算子をオーバーロード可能
local function make_account(balance)
return {
deposit = function(n) balance = balance + n end,
withdraw = function(n) balance = balance - n end,
get = function() return balance end,
}
end
local acc = make_account(100)
acc.deposit(50)
acc.withdraw(30)
print(acc.get()) -- 120
-- 'balance' is private: only the methods can touch it__index継承
__indexによる継承
local function fibgen()
local a, b = 0, 1
return function()
a, b = b, a + b
return a
end
end
local next_fib = fibgen()
for i = 1, 8 do
io.write(next_fib(), " ") -- 1 1 2 3 5 8 13 21
end
print()__newindex
__newindexは代入をインターセプト
local function memoize(fn)
local cache = {}
return function(x)
if cache[x] == nil then
cache[x] = fn(x)
end
return cache[x]
end
end
local function slow_square(n)
-- pretend this is expensive
return n * n
end
local fast_square = memoize(slow_square)
print(fast_square(5)) -- 25 (computed)
print(fast_square(5)) -- 25 (cached)__call
__callはテーブルを関数のように呼び出し可能に
local function adder(x)
-- 'x' is an upvalue for the returned function
return function(y) return x + y end
end
local add5 = adder(5)
local add10 = adder(10)
print(add5(3)) -- 8
print(add10(3)) -- 13
-- each call to adder creates a separate upvalue
-- block scope with do-end
do
local tmp = "hidden"
end
-- print(tmp) -- error: tmp is out of scopeOOP
クラスのシミュレーション
テーブルとメタテーブルでクラスをシミュレート
local t = {}
local mt = {}
setmetatable(t, mt)
print(getmetatable(t) == mt) -- true
-- setmetatable returns the table, so chain inline
local t2 = setmetatable({key = 1}, {
__tostring = function(self) return "MyTable" end,
})
print(tostring(t2)) -- MyTableオブジェクトの作成
:呼び出しは自動的にselfを渡す
local defaults = {color = "red", size = 10}
local obj = {color = "blue"}
setmetatable(obj, {__index = defaults})
print(obj.color) -- blue (own key wins)
print(obj.size) -- 10 (falls back to defaults)
print(obj.shape) -- nil (not found anywhere)
-- __index can also be a function: __index = function(t, k) ...継承
メタテーブルチェーンによる継承
local log = {}
local t = setmetatable({}, {
__newindex = function(t, k, v)
log[k] = v -- record the assignment
rawset(t, k, v) -- actually store it (avoid recursion)
end,
})
t.x = 5 -- triggers __newindex
print(log.x, t.x) -- 5 5
-- rawset/rawget bypass metamethodsメソッドオーバーライド
サブクラスのメソッドが親をオーバーライド
local Vec = {}
Vec.__index = Vec
Vec.__add = function(a, b) return Vec.new(a.x + b.x, a.y + b.y) end
Vec.__mul = function(a, n) return Vec.new(a.x * n, a.y * n) end
function Vec.new(x, y)
return setmetatable({x = x, y = y}, Vec)
end
local v1 = Vec.new(1, 2)
local v2 = Vec.new(3, 4)
local v3 = v1 + v2 -- uses __add
local v4 = v1 * 10 -- uses __mul
print(v3.x, v3.y) -- 4 6Comparison Metamethods
Comparison metamethods are __eq, __lt, and __le (Lua derives the others). They only apply when both operands share the same metamethod, and __eq requires both values to be of the same type.
local Money = {}
Money.__index = Money
Money.__lt = function(a, b) return a.cents < b.cents end
Money.__le = function(a, b) return a.cents <= b.cents end
Money.__eq = function(a, b) return a.cents == b.cents end
local function money(cents)
return setmetatable({cents = cents}, Money)
end
print(money(100) < money(200)) -- true
print(money(100) == money(100)) -- true__call & __tostring
__call makes a table callable as a function (great for functors and factories). __tostring controls how tostring() and print() render the table. Both dramatically improve the ergonomics of custom types.
local Greeter = {}
Greeter.__index = Greeter
Greeter.__call = function(self, who)
return "Hi " .. who .. ", I am " .. self.name
end
Greeter.__tostring = function(self)
return "Greeter(" .. self.name .. ")"
end
local g = setmetatable({name = "Bot"}, Greeter)
print(g("Alice")) -- Hi Alice, I am Bot
print(tostring(g)) -- Greeter(Bot)
-- __call lets a table be invoked like a functionコルーチン
コルーチンの作成
coroutine.createはコルーチンを作成
local Animal = {}
Animal.__index = Animal
function Animal.new(name)
local self = setmetatable({}, Animal)
self.name = name
return self
end
function Animal:speak()
return self.name .. " makes a sound"
end
local a = Animal.new("Cat")
print(a:speak()) -- Cat makes a soundコルーチンの再開
resumeはコルーチンを開始または再開
local Counter = {}
Counter.__index = Counter
function Counter.new()
return setmetatable({count = 0}, Counter)
end
-- the colon ':' adds an implicit 'self' parameter
function Counter:inc()
self.count = self.count + 1
end
local c = Counter.new()
c:inc() -- sugar for Counter.inc(c)
c:inc()
print(c.count) -- 2コルーチンの状態
コルーチンには4つの状態があります
local Point = {}
Point.__index = Point
function Point.new(x, y)
local obj = setmetatable({}, Point)
obj.x = x or 0
obj.y = y or 0
return obj
end
function Point:distance(other)
local dx, dy = self.x - other.x, self.y - other.y
return math.sqrt(dx*dx + dy*dy)
end
local p1 = Point.new(0, 0)
local p2 = Point.new(3, 4)
print(p1:distance(p2)) -- 5yield値渡し
yieldとresumeは双方向に値を渡せます
local Animal = {}
Animal.__index = Animal
function Animal.new(name) return setmetatable({name = name}, Animal) end
function Animal:speak() return self.name .. " speaks" end
local Dog = setmetatable({}, {__index = Animal})
Dog.__index = Dog
function Dog.new(name)
return setmetatable(Animal.new(name), Dog)
end
function Dog:bark() return self.name .. " barks!" end
local d = Dog.new("Rex")
print(d:speak()) -- Rex speaks (inherited from Animal)
print(d:bark()) -- Rex barks! (Dog's own method)コルーチンイテレータ
coroutine.wrapは呼び出し可能な関数を返します
local Shape = {}
Shape.__index = Shape
function Shape.new() return setmetatable({}, Shape) end
function Shape:area() return 0 end
local Circle = setmetatable({}, {__index = Shape})
Circle.__index = Circle
function Circle.new(r) return setmetatable({r = r}, Circle) end
function Circle:area() return math.pi * self.r * self.r end -- override
local c = Circle.new(2)
print(c:area()) -- 12.566...
-- call the parent method explicitly: Shape.area(c)Class-based Inheritance Pattern
A small Class() helper standardizes creation and inheritance: new() builds an instance and calls init if present. This pattern is the basis of many Lua OOP libraries (middleclass, classic, etc.).
local function Class(base)
local cls = {}
cls.__index = cls
if base then setmetatable(cls, {__index = base}) end
cls.new = function(...)
local obj = setmetatable({}, cls)
if obj.init then obj:init(...) end
return obj
end
return cls
end
local Vehicle = Class()
function Vehicle:init(wheels) self.wheels = wheels end
function Vehicle:desc() return self.wheels .. " wheels" end
local Bike = Class(Vehicle)
function Bike:init() Vehicle.init(self, 2) end
print(Bike.new():desc()) -- 2 wheelsモジュール
モジュールの定義
モジュール機能を含むテーブルを返します
local co = coroutine.create(function(a, b)
print("start", a, b)
local c = coroutine.yield(a + b)
print("resumed with", c)
return "done"
end)
-- coroutine.create returns a thread
print(type(co)) -- thread
print(coroutine.status(co)) -- suspendedモジュールの使用
requireはモジュールを一度だけ読み込みます
local co = coroutine.create(function()
for i = 1, 3 do
coroutine.yield(i)
end
end)
print(coroutine.resume(co)) -- true 1
print(coroutine.resume(co)) -- true 2
print(coroutine.resume(co)) -- true 3
print(coroutine.resume(co)) -- true (no more values)
print(coroutine.status(co)) -- deadモジュールパス
?.luaの?はモジュール名に置換
-- states: suspended, running, normal, dead
local co = coroutine.create(function()
coroutine.yield()
end)
print(coroutine.status(co)) -- suspended
coroutine.resume(co)
print(coroutine.status(co)) -- suspended (yielded)
coroutine.resume(co)
print(coroutine.status(co)) -- dead
-- coroutine.running() returns the current coroutine (nil in main)
print(coroutine.running()) -- nil (main thread)リロード
キャッシュをクリアしてから再度require
local co = coroutine.create(function(x)
local y = coroutine.yield(x * 2) -- sends x*2, receives y
local z = coroutine.yield(y * 3) -- sends y*3, receives z
return z
end)
print(coroutine.resume(co, 10)) -- true 20 (x=10, yields 20)
print(coroutine.resume(co, 5)) -- true 15 (y=5, yields 15)
print(coroutine.resume(co, 7)) -- true 7 (z=7, returns 7)coroutine.wrap
coroutine.wrap returns a plain function that resumes the coroutine each call—more convenient than create+resume and perfect for iterators. The trade-off: errors raise instead of returning (ok, err), so there's no built-in error flag.
-- wrap returns a function (not a thread); it auto-resumes
-- and propagates errors instead of returning ok
local gen = coroutine.wrap(function()
for i = 1, 5 do
coroutine.yield(i * i)
end
end)
print(gen()) -- 1
print(gen()) -- 4
print(gen()) -- 9
-- ideal for iterator-style use
for v in coroutine.wrap(function()
coroutine.yield("a"); coroutine.yield("b")
end) do
print(v) -- a, then b
break
endエラー処理
errorスロー
errorは例外をスロー
-- file: mymath.lua
local M = {}
function M.square(n) return n * n end
function M.cube(n) return n * n * n end
M.pi = 3.14159
return M
-- a module is just a table returned by the chunkpcall保護呼び出し
pcallはエラーを捕捉
-- require loads the module and caches it in package.loaded
local mymath = require("mymath")
print(mymath.square(5)) -- 25
print(mymath.cube(3)) -- 27
print(mymath.pi) -- 3.14159
-- subsequent requires return the cached table
local m2 = require("mymath")
print(m2 == mymath) -- true
-- dotted names map to paths: a.b.c -> a/b/c.luaxpcallとtraceback
xpcallはエラーハンドラの指定を許可
-- package.path controls where require looks for Lua modules
print(package.path)
-- patterns like ./?.lua;./?/init.lua;? is the module name
-- add a custom directory
package.path = "./libs/?.lua;" .. package.path
-- require("foo") then tries ./libs/foo.lua
-- package.cpath is the equivalent for compiled C modules
-- (?.so on Unix, ?.dll on Windows)assert
assertは条件が偽のときスロー
-- require caches in package.loaded; clear it to reload
package.loaded["mymath"] = nil
local mymath = require("mymath") -- re-runs the chunk
-- a hot-reload helper
local function reload(name)
package.loaded[name] = nil
return require(name)
end
-- warning: existing references to the old table
-- are NOT updated after a reloaderrorレベル
第2パラメータがエラー位置を制御
-- pattern 1: return a table (most common)
local M = {}
function M.fn() end
return M
-- pattern 2: keep helpers local, export a clean table
local function helper() end
local function main_fn() helper() end
return { main = main_fn }
-- pattern 3: module() (legacy, Lua 5.1) -- deprecated
-- module("foo"); function _M.fn() end