Lua
#20
TIOBE#30
PYPL#19
GitHub#26
IEEESpectrum#15
JetBrains#17
プログラミング言語
Lua
概要
Luaは軽量で高速な組み込み用スクリプト言語で、ゲーム開発、組み込みシステム、設定スクリプトで使用されます。
詳細
Luaは1993年にブラジルの研究グループによって開発された軽量なプログラミング言語です。「Lua」はポルトガル語で「月」を意味します。わずか数十キロバイトの非常に小さなインタープリターでありながら、強力な機能を持つことで知られています。C言語で実装され、C/C++アプリケーションに簡単に組み込むことができるため、主に他のアプリケーションの拡張言語として使用されます。ゲーム業界では特に人気が高く、World of Warcraft、Angry Birds、Robloxなど多くの有名ゲームで使用されています。シンプルで直感的な構文、動的型付け、自動メモリ管理、強力なテーブル機能を特徴とし、小さなフットプリントながら高いパフォーマンスを実現しています。組み込みシステム、設定ファイル、ネットワーク機器のスクリプトなど、幅広い分野で活用されています。
書き方の例
Hello World
-- 基本的な出力
print("Hello, World!")
-- 複数の値を出力
print("Hello,", "Lua!")
-- 変数を使った出力
local message = "こんにちは、Lua!"
print(message)
-- 文字列の連結
local name = "太郎"
local age = 25
print("私の名前は" .. name .. "で、" .. age .. "歳です。")
-- string.format を使った書式設定
local formatted = string.format("私の名前は%sで、%d歳です。", name, age)
print(formatted)
-- 関数を使った例
function greet(name)
return "こんにちは、" .. name .. "さん!"
end
print(greet("山田"))
-- ローカル関数
local function createMessage(name, age)
return string.format("名前: %s, 年齢: %d", name, age)
end
print(createMessage("佐藤", 30))
-- 複数行の文字列
local multiline = [[
これは複数行の
文字列です。
Luaでは[[]]で囲みます。
]]
print(multiline)
-- 条件付き出力
local debug = true
if debug then
print("デバッグモードが有効です")
end
-- ループを使った例
for i = 1, 5 do
print("Hello " .. i .. "回目!")
end
-- テーブルを使った例
local fruits = {"りんご", "バナナ", "オレンジ"}
for i, fruit in ipairs(fruits) do
print(i .. "番目の果物: " .. fruit)
end
-- 時刻の表示
print("現在時刻: " .. os.date("%Y-%m-%d %H:%M:%S"))
-- ファイルへの出力例
local function writeToFile()
local file = io.open("hello.txt", "w")
if file then
file:write("Hello, World from Lua!\n")
file:write("日本語も書けます\n")
file:close()
print("ファイルに書き込みました: hello.txt")
else
print("ファイルの作成に失敗しました")
end
end
writeToFile()
-- スタンドアロンスクリプトとしての実行
if arg and arg[0] then
print("スクリプトファイル: " .. arg[0])
if arg[1] then
print("引数1: " .. arg[1])
end
end
変数とデータ型
-- Luaにはローカル変数とグローバル変数がある
-- localキーワードを使わないとグローバル変数になる
-- 基本的なデータ型
local stringValue = "文字列"
local numberValue = 42
local floatValue = 3.14159
local booleanValue = true
local nilValue = nil
print("=== 基本データ型 ===")
print("文字列:", stringValue, type(stringValue))
print("整数:", numberValue, type(numberValue))
print("浮動小数点:", floatValue, type(floatValue))
print("真偽値:", booleanValue, type(booleanValue))
print("nil値:", nilValue, type(nilValue))
-- Luaでは整数と浮動小数点は区別されない(Lua 5.3以降で区別可能)
local int = 10
local float = 10.0
print("整数か?:", math.type and math.type(int) or "number")
print("浮動小数点か?:", math.type and math.type(float) or "number")
-- 文字列操作
local str1 = "Hello"
local str2 = "World"
local combined = str1 .. " " .. str2 -- 文字列連結
print("連結:", combined)
print("長さ:", #combined)
print("大文字:", string.upper(combined))
print("小文字:", string.lower(combined))
print("部分文字列:", string.sub(combined, 1, 5))
print("置換:", string.gsub(combined, "World", "Lua"))
-- 文字列内の数値変換
local numStr = "123"
local strNum = 456
print("文字列→数値:", tonumber(numStr), type(tonumber(numStr)))
print("数値→文字列:", tostring(strNum), type(tostring(strNum)))
-- エスケープシーケンス
local escaped = "改行\n タブ\t 引用符\" バックスラッシュ\\"
print("エスケープ文字列:")
print(escaped)
-- 長い文字列リテラル
local longString = [[
複数行にわたる
長い文字列を
記述できます。
エスケープ文字は無視されます: \n \t \"
]]
print("長い文字列:", longString)
-- テーブル(Luaの最も重要なデータ構造)
print("\n=== テーブル ===")
-- 配列として使用
local array = {10, 20, 30, 40, 50}
print("配列:")
for i = 1, #array do -- Luaの配列は1から始まる
print(" [" .. i .. "] = " .. array[i])
end
-- 辞書(ハッシュテーブル)として使用
local dict = {
name = "田中太郎",
age = 25,
city = "東京",
isActive = true
}
print("\n辞書:")
for key, value in pairs(dict) do
print(" " .. key .. " = " .. tostring(value))
end
-- 混合テーブル(配列と辞書の機能を同時に)
local mixed = {
"最初の要素", -- [1]
"2番目の要素", -- [2]
name = "混合テーブル",
count = 2
}
print("\n混合テーブル:")
print(" [1] =", mixed[1])
print(" [2] =", mixed[2])
print(" name =", mixed.name)
print(" count =", mixed.count)
-- ネストしたテーブル
local nested = {
personal = {
name = "山田花子",
age = 30
},
work = {
company = "サンプル会社",
position = "エンジニア"
},
hobbies = {"読書", "映画鑑賞", "プログラミング"}
}
print("\nネストしたテーブル:")
print(" 名前:", nested.personal.name)
print(" 年齢:", nested.personal.age)
print(" 会社:", nested.work.company)
print(" 趣味:")
for i, hobby in ipairs(nested.hobbies) do
print(" " .. i .. ". " .. hobby)
end
-- テーブルの動的操作
local dynamic = {}
dynamic.name = "動的テーブル"
dynamic[1] = "最初の要素"
dynamic["key with spaces"] = "スペースを含むキー"
-- table.insert と table.remove
table.insert(dynamic, "追加された要素")
table.insert(dynamic, 2, "2番目に挿入")
print("\n動的テーブル:")
for k, v in pairs(dynamic) do
print(" " .. tostring(k) .. " = " .. tostring(v))
end
-- 変数のスコープ
globalVar = "グローバル変数" -- localなし
do
local localVar = "ローカル変数"
print("\nスコープテスト:")
print(" ブロック内 - グローバル:", globalVar)
print(" ブロック内 - ローカル:", localVar)
end
print("ブロック外 - グローバル:", globalVar)
-- print("ブロック外 - ローカル:", localVar) -- エラーになる
-- 複数代入
local a, b, c = 1, 2, 3
local x, y = "Hello", "World"
print("\n複数代入:")
print("a, b, c =", a, b, c)
print("x, y =", x, y)
-- 値の交換
a, b = b, a
print("交換後: a, b =", a, b)
-- 関数から複数の値を返す
local function getNameAge()
return "佐藤次郎", 35
end
local name, age = getNameAge()
print("関数からの複数戻り値:", name, age)
-- weak参照テーブル(ガベージコレクション関連)
local weak = {}
setmetatable(weak, {__mode = "v"}) -- 値をweak参照に
weak[1] = {data = "テストデータ"}
print("\nWeak参照テーブル作成完了")
関数と制御構造
-- 基本的な関数定義
function add(a, b)
return a + b
end
-- ローカル関数
local function multiply(a, b)
return a * b
end
-- 無名関数(関数リテラル)
local subtract = function(a, b)
return a - b
end
print("=== 基本的な関数 ===")
print("足し算:", add(5, 3))
print("掛け算:", multiply(4, 6))
print("引き算:", subtract(10, 3))
-- 可変引数関数
local function sum(...)
local args = {...} -- 可変引数をテーブルに変換
local total = 0
for i = 1, #args do
total = total + args[i]
end
return total
end
print("可変引数の合計:", sum(1, 2, 3, 4, 5))
-- select関数を使った可変引数処理
local function printArgs(...)
print("引数の数:", select("#", ...))
for i = 1, select("#", ...) do
print(" 引数" .. i .. ":", select(i, ...))
end
end
print("\n可変引数のテスト:")
printArgs("Hello", "World", 123, true)
-- 複数の戻り値
local function getMinMax(...)
local args = {...}
if #args == 0 then return nil, nil end
local min, max = args[1], args[1]
for i = 2, #args do
if args[i] < min then min = args[i] end
if args[i] > max then max = args[i] end
end
return min, max
end
local minimum, maximum = getMinMax(5, 2, 8, 1, 9, 3)
print("\n最小値・最大値:", minimum, maximum)
-- クロージャ(関数内関数)
local function createCounter(initial)
local count = initial or 0
return function()
count = count + 1
return count
end
end
local counter1 = createCounter(0)
local counter2 = createCounter(100)
print("\nクロージャのテスト:")
print("カウンタ1:", counter1(), counter1(), counter1()) -- 1, 2, 3
print("カウンタ2:", counter2(), counter2()) -- 101, 102
-- 高階関数(関数を引数に取る関数)
local function applyToArray(arr, func)
local result = {}
for i, v in ipairs(arr) do
result[i] = func(v)
end
return result
end
local numbers = {1, 2, 3, 4, 5}
local doubled = applyToArray(numbers, function(x) return x * 2 end)
local squared = applyToArray(numbers, function(x) return x * x end)
print("\n高階関数:")
print("元の配列:", table.concat(numbers, ", "))
print("2倍:", table.concat(doubled, ", "))
print("2乗:", table.concat(squared, ", "))
-- 条件分岐
print("\n=== 条件分岐 ===")
local score = 85
if score >= 90 then
print("優秀")
elseif score >= 80 then
print("良好")
elseif score >= 70 then
print("普通")
elseif score >= 60 then
print("要改善")
else
print("不合格")
end
-- 三項演算子の代替(and/or演算子)
local grade = score >= 60 and "合格" or "不合格"
print("結果:", grade)
-- ループ構造
print("\n=== ループ構造 ===")
-- 数値forループ
print("数値forループ:")
for i = 1, 5 do
print(" カウント:", i)
end
print("ステップ付きforループ:")
for i = 10, 2, -2 do -- 10から2まで-2ずつ
print(" 逆順:", i)
end
-- generic forループ(イテレータ)
local fruits = {"りんご", "バナナ", "オレンジ", "いちご"}
print("ipairs使用(インデックス付き):")
for index, fruit in ipairs(fruits) do
print(" " .. index .. ": " .. fruit)
end
local person = {name = "田中", age = 30, city = "東京"}
print("pairs使用(キー・値):")
for key, value in pairs(person) do
print(" " .. key .. " = " .. tostring(value))
end
-- whileループ
print("whileループ:")
local count = 1
while count <= 3 do
print(" while:", count)
count = count + 1
end
-- repeatループ(do-while相当)
print("repeatループ:")
count = 1
repeat
print(" repeat:", count)
count = count + 1
until count > 3
-- break と 制御構造
print("break文の使用:")
for i = 1, 10 do
if i == 5 then
print(" 5で中断")
break
end
print(" 値:", i)
end
-- goto文(Lua 5.2以降)
print("goto文の例:")
local i = 1
::loop::
if i <= 3 then
print(" goto:", i)
i = i + 1
goto loop
end
-- エラーハンドリング
print("\n=== エラーハンドリング ===")
-- pcall(protected call)を使った安全な関数呼び出し
local function riskyFunction(x)
if x == 0 then
error("ゼロは許可されていません")
end
return 10 / x
end
local success, result = pcall(riskyFunction, 5)
if success then
print("成功:", result)
else
print("エラー:", result)
end
local success, result = pcall(riskyFunction, 0)
if success then
print("成功:", result)
else
print("エラー:", result)
end
-- xpcall(extended pcall)でエラーハンドラを指定
local function errorHandler(err)
return "エラーハンドラで処理: " .. tostring(err)
end
local success, result = xpcall(function() return riskyFunction(0) end, errorHandler)
print("xpcall結果:", success, result)
-- assert関数
local function validateAge(age)
assert(type(age) == "number", "年齢は数値である必要があります")
assert(age >= 0 and age <= 150, "年齢は0-150の範囲である必要があります")
return age
end
local validAge = validateAge(25)
print("有効な年齢:", validAge)
-- 無効な年齢でテスト(コメントアウト)
-- local invalidAge = validateAge("abc") -- エラーになる
テーブルとメタテーブル
-- Luaの最も強力な機能の一つ:メタテーブル
print("=== テーブルの高度な操作 ===")
-- 基本的なテーブル操作
local array = {10, 20, 30}
print("元の配列:", table.concat(array, ", "))
-- 要素の追加
table.insert(array, 40) -- 末尾に追加
table.insert(array, 2, 15) -- 2番目の位置に挿入
print("追加後:", table.concat(array, ", "))
-- 要素の削除
local removed = table.remove(array, 2) -- 2番目の要素を削除
print("削除された要素:", removed)
print("削除後:", table.concat(array, ", "))
-- ソート
local unsorted = {3, 1, 4, 1, 5, 9, 2, 6}
table.sort(unsorted)
print("ソート後:", table.concat(unsorted, ", "))
-- カスタムソート
local names = {"田中", "佐藤", "鈴木", "高橋"}
table.sort(names, function(a, b) return #a < #b end) -- 文字数でソート
print("文字数でソート:", table.concat(names, ", "))
-- メタテーブルの基本
print("\n=== メタテーブル ===")
-- 単純なメタテーブル例
local mt = {
__add = function(a, b)
return {x = a.x + b.x, y = a.y + b.y}
end,
__tostring = function(t)
return string.format("Point(%d, %d)", t.x, t.y)
end,
__index = function(t, key)
if key == "magnitude" then
return math.sqrt(t.x^2 + t.y^2)
end
return nil
end
}
local point1 = {x = 3, y = 4}
local point2 = {x = 1, y = 2}
setmetatable(point1, mt)
setmetatable(point2, mt)
-- メタメソッドの使用
local point3 = point1 + point2 -- __add メタメソッド
print("点の加算:", tostring(point3)) -- __tostring メタメソッド
print("point1の大きさ:", point1.magnitude) -- __index メタメソッド
-- クラスライクなオブジェクト
print("\n=== オブジェクト指向プログラミング ===")
-- Personクラスの定義
local Person = {}
Person.__index = Person
function Person:new(name, age)
local obj = {
name = name or "無名",
age = age or 0
}
setmetatable(obj, self)
return obj
end
function Person:introduce()
return string.format("私の名前は%sで、%d歳です。", self.name, self.age)
end
function Person:haveBirthday()
self.age = self.age + 1
print(self.name .. "さん、" .. self.age .. "歳のお誕生日おめでとう!")
end
function Person:__tostring()
return string.format("Person{name='%s', age=%d}", self.name, self.age)
end
-- オブジェクトの作成と使用
local person1 = Person:new("田中太郎", 25)
local person2 = Person:new("山田花子", 30)
print("person1:", person1:introduce())
print("person2:", person2:introduce())
person1:haveBirthday()
print("誕生日後:", tostring(person1))
-- 継承の例
local Student = {}
Student.__index = Student
setmetatable(Student, Person) -- PersonからStudent への継承
function Student:new(name, age, school)
local obj = Person.new(self, name, age)
obj.school = school or "未設定"
setmetatable(obj, self)
return obj
end
function Student:introduce()
local base = Person.introduce(self)
return base .. " " .. self.school .. "に通っています。"
end
function Student:study(subject)
print(self.name .. "は" .. subject .. "を勉強しています。")
end
local student = Student:new("佐藤一郎", 20, "東京大学")
print("学生の紹介:", student:introduce())
student:study("数学")
-- プロキシテーブル(プロパティアクセスの制御)
print("\n=== プロキシテーブル ===")
local function createReadOnlyTable(t)
local proxy = {}
local mt = {
__index = t,
__newindex = function(table, key, value)
error("読み取り専用テーブルへの書き込みは禁止されています")
end
}
setmetatable(proxy, mt)
return proxy
end
local config = {
version = "1.0",
author = "開発者",
debug = true
}
local readOnlyConfig = createReadOnlyTable(config)
print("バージョン:", readOnlyConfig.version)
print("作者:", readOnlyConfig.author)
-- 書き込みテスト(エラーになる)
-- readOnlyConfig.version = "2.0" -- エラー
-- プロパティアクセスの監視
local function createWatchedTable()
local data = {}
local watchers = {}
local mt = {
__index = data,
__newindex = function(t, key, value)
local oldValue = data[key]
data[key] = value
-- ウォッチャーに通知
for _, watcher in ipairs(watchers) do
watcher(key, oldValue, value)
end
end
}
local proxy = {}
setmetatable(proxy, mt)
-- ウォッチャー追加メソッド
proxy.addWatcher = function(watcher)
table.insert(watchers, watcher)
end
return proxy
end
local watched = createWatchedTable()
watched.addWatcher(function(key, oldVal, newVal)
print(string.format("プロパティ変更: %s = %s → %s",
key, tostring(oldVal), tostring(newVal)))
end)
watched.name = "テスト"
watched.count = 1
watched.count = 2
モジュールとパッケージ
-- Luaでのモジュールシステム
print("=== モジュールの基本 ===")
-- シンプルなモジュール作成例
local mymath = {}
function mymath.add(a, b)
return a + b
end
function mymath.multiply(a, b)
return a * b
end
mymath.pi = 3.14159
-- プライベート関数(モジュール外からアクセス不可)
local function privateHelper(x)
return x * 2
end
function mymath.doubleAndAdd(a, b)
return privateHelper(a) + b
end
-- モジュールの使用
print("mymath.add(5, 3):", mymath.add(5, 3))
print("mymath.multiply(4, 6):", mymath.multiply(4, 6))
print("mymath.pi:", mymath.pi)
print("mymath.doubleAndAdd(5, 3):", mymath.doubleAndAdd(5, 3))
-- より高度なモジュールパターン
print("\n=== 高度なモジュールパターン ===")
-- 名前空間を持つモジュール
local utils = {}
utils.string = {}
utils.table = {}
utils.math = {}
-- 文字列ユーティリティ
function utils.string.trim(s)
return s:gsub("^%s*(.-)%s*$", "%1")
end
function utils.string.split(str, delimiter)
local result = {}
local pattern = string.format("([^%s]+)", delimiter)
for match in str:gmatch(pattern) do
table.insert(result, match)
end
return result
end
-- テーブルユーティリティ
function utils.table.deepCopy(orig)
local copy
if type(orig) == 'table' then
copy = {}
for orig_key, orig_value in next, orig, nil do
copy[utils.table.deepCopy(orig_key)] = utils.table.deepCopy(orig_value)
end
setmetatable(copy, utils.table.deepCopy(getmetatable(orig)))
else
copy = orig
end
return copy
end
function utils.table.isEmpty(t)
return next(t) == nil
end
-- 数学ユーティリティ
function utils.math.clamp(value, min, max)
return math.max(min, math.min(max, value))
end
function utils.math.lerp(a, b, t)
return a + (b - a) * t
end
-- ユーティリティの使用例
print("文字列のトリム:", "'" .. utils.string.trim(" hello world ") .. "'")
local parts = utils.string.split("apple,banana,orange", ",")
print("文字列分割:")
for i, part in ipairs(parts) do
print(" " .. i .. ": " .. part)
end
local original = {a = 1, b = {c = 2, d = 3}}
local copied = utils.table.deepCopy(original)
copied.b.c = 999
print("元のテーブル b.c:", original.b.c) -- 2(変更されない)
print("コピーのテーブル b.c:", copied.b.c) -- 999
print("clamp(15, 0, 10):", utils.math.clamp(15, 0, 10))
print("lerp(0, 100, 0.5):", utils.math.lerp(0, 100, 0.5))
-- ファクトリパターン
print("\n=== ファクトリパターン ===")
local function createLogger(name)
local logger = {}
function logger.info(message)
print(string.format("[INFO][%s] %s", name, message))
end
function logger.warn(message)
print(string.format("[WARN][%s] %s", name, message))
end
function logger.error(message)
print(string.format("[ERROR][%s] %s", name, message))
end
return logger
end
local appLogger = createLogger("App")
local dbLogger = createLogger("Database")
appLogger.info("アプリケーション開始")
dbLogger.warn("接続が遅いです")
appLogger.error("予期しないエラー")
-- シングルトンパターン
print("\n=== シングルトンパターン ===")
local ConfigManager = {}
local instance = nil
function ConfigManager.getInstance()
if not instance then
instance = {
settings = {},
set = function(self, key, value)
self.settings[key] = value
end,
get = function(self, key, default)
return self.settings[key] or default
end,
dump = function(self)
print("設定内容:")
for k, v in pairs(self.settings) do
print(" " .. k .. " = " .. tostring(v))
end
end
}
end
return instance
end
-- シングルトンの使用
local config1 = ConfigManager.getInstance()
local config2 = ConfigManager.getInstance()
config1:set("debug", true)
config2:set("version", "1.0")
print("config1とconfig2は同じインスタンス?", config1 == config2)
config1:dump()
-- パッケージローダーのシミュレーション
print("\n=== パッケージシステムのシミュレーション ===")
local packageSystem = {}
packageSystem.loaded = {}
function packageSystem.require(name)
if packageSystem.loaded[name] then
return packageSystem.loaded[name]
end
-- 実際のシステムではファイルから読み込む
local module
if name == "json" then
module = {
encode = function(t) return "JSON encoded: " .. tostring(t) end,
decode = function(s) return {decoded = s} end
}
elseif name == "http" then
module = {
get = function(url) return "HTTP GET: " .. url end,
post = function(url, data) return "HTTP POST to " .. url end
}
else
error("モジュール '" .. name .. "' が見つかりません")
end
packageSystem.loaded[name] = module
return module
end
-- パッケージの使用
local json = packageSystem.require("json")
local http = packageSystem.require("http")
print("JSONエンコード:", json.encode({test = "data"}))
print("HTTP GET:", http.get("http://example.com"))
-- 2回目の require は既にロードされたものを返す
local json2 = packageSystem.require("json")
print("同じインスタンス?", json == json2)
ファイル操作とC言語連携
-- ファイル入出力操作
print("=== ファイル入出力 ===")
-- ファイルへの書き込み
local function writeToFile()
local filename = "test.txt"
local file = io.open(filename, "w")
if file then
file:write("Hello, Lua!\n")
file:write("これはテストファイルです。\n")
file:write("現在時刻: " .. os.date("%Y-%m-%d %H:%M:%S") .. "\n")
-- 数値データの書き込み
for i = 1, 5 do
file:write(string.format("数値 %d: %d\n", i, i * i))
end
file:close()
print("ファイルに書き込み完了: " .. filename)
return true
else
print("ファイルの作成に失敗しました")
return false
end
end
-- ファイルからの読み込み
local function readFromFile()
local filename = "test.txt"
local file = io.open(filename, "r")
if file then
print("\nファイル内容:")
print("=" .. string.rep("=", 30))
-- 全体を一度に読み込み
local content = file:read("*all")
file:close()
print(content)
print("=" .. string.rep("=", 30))
return true
else
print("ファイルの読み込みに失敗しました")
return false
end
end
-- 行ごとの読み込み
local function readLineByLine()
local filename = "test.txt"
local file = io.open(filename, "r")
if file then
print("\n行ごとの読み込み:")
local lineNumber = 1
for line in file:lines() do
print(string.format("行%d: %s", lineNumber, line))
lineNumber = lineNumber + 1
end
file:close()
return true
else
print("ファイルの読み込みに失敗しました")
return false
end
end
-- バイナリファイル操作
local function binaryFileOperations()
local filename = "binary.dat"
-- バイナリ書き込み
local file = io.open(filename, "wb")
if file then
-- いくつかのバイト値を書き込み
for i = 0, 255, 17 do
file:write(string.char(i))
end
file:close()
print("バイナリファイル作成完了: " .. filename)
end
-- バイナリ読み込み
file = io.open(filename, "rb")
if file then
print("バイナリファイル内容:")
local byte = file:read(1)
local position = 1
while byte do
print(string.format("位置%d: %d (0x%02X)", position, string.byte(byte), string.byte(byte)))
byte = file:read(1)
position = position + 1
end
file:close()
end
end
-- CSV ファイル操作
local function csvOperations()
local csvFile = "data.csv"
-- CSVファイル作成
local file = io.open(csvFile, "w")
if file then
file:write("名前,年齢,部署,給与\n")
file:write("田中太郎,25,営業部,300000\n")
file:write("佐藤花子,30,開発部,400000\n")
file:write("山田一郎,35,管理部,350000\n")
file:close()
print("CSVファイル作成完了: " .. csvFile)
end
-- CSV読み込みと解析
file = io.open(csvFile, "r")
if file then
print("\nCSVデータ:")
local header = file:read("*line")
print("ヘッダー: " .. header)
local rowNumber = 1
for line in file:lines() do
local fields = {}
for field in line:gmatch("([^,]+)") do
table.insert(fields, field)
end
print(string.format("行%d: 名前=%s, 年齢=%s, 部署=%s, 給与=%s円",
rowNumber, fields[1], fields[2], fields[3], fields[4]))
rowNumber = rowNumber + 1
end
file:close()
end
end
-- ファイル操作の実行
if writeToFile() then
readFromFile()
readLineByLine()
end
binaryFileOperations()
csvOperations()
-- システム情報とOS操作
print("\n=== システム情報 ===")
print("OS時刻:", os.date("%Y-%m-%d %H:%M:%S"))
print("UTC時刻:", os.date("!%Y-%m-%d %H:%M:%S"))
print("エポック時間:", os.time())
-- 日付計算
local birthday = os.time{year=1990, month=5, day=15}
local now = os.time()
local ageInSeconds = now - birthday
local ageInDays = math.floor(ageInSeconds / (24 * 60 * 60))
print("生年月日から今日まで:", ageInDays .. "日")
-- 環境変数(存在する場合)
local home = os.getenv("HOME") or os.getenv("USERPROFILE")
if home then
print("ホームディレクトリ:", home)
end
local path = os.getenv("PATH")
if path then
print("PATH環境変数の長さ:", #path .. "文字")
end
-- C言語ライブラリ関数の使用例
print("\n=== C言語ライブラリ関数 ===")
-- 数学ライブラリ
print("数学関数:")
print("sin(π/2):", math.sin(math.pi / 2))
print("cos(0):", math.cos(0))
print("sqrt(16):", math.sqrt(16))
print("log(math.e):", math.log(math.e))
print("random(1,10):", math.random(1, 10))
-- 乱数のシード設定
math.randomseed(os.time())
print("ランダム配列:")
local randomNumbers = {}
for i = 1, 5 do
randomNumbers[i] = math.random(1, 100)
end
print(" " .. table.concat(randomNumbers, ", "))
-- 文字列ライブラリ
print("\n文字列関数:")
local testString = "Hello, Lua Programming!"
print("元の文字列:", testString)
print("大文字:", string.upper(testString))
print("小文字:", string.lower(testString))
print("文字列の長さ:", string.len(testString))
print("部分文字列(8-10):", string.sub(testString, 8, 10))
-- パターンマッチング
local email = "[email protected]"
local username, domain = string.match(email, "([^@]+)@([^@]+)")
print("メール解析:")
print(" ユーザー名:", username)
print(" ドメイン:", domain)
-- 文字列置換
local text = "今日は晴れです。明日も晴れでしょう。"
local replaced = string.gsub(text, "晴れ", "雨")
print("置換前:", text)
print("置換後:", replaced)
-- テーブルライブラリ
print("\nテーブル関数:")
local fruits = {"りんご", "バナナ", "オレンジ", "いちご"}
print("元の配列:", table.concat(fruits, ", "))
table.sort(fruits)
print("ソート後:", table.concat(fruits, ", "))
local numbers = {3, 1, 4, 1, 5, 9, 2, 6}
table.sort(numbers, function(a, b) return a > b end) -- 降順
print("降順ソート:", table.concat(numbers, ", "))
-- 簡単なC言語連携のシミュレーション(実際にはC言語側の実装が必要)
print("\n=== C言語連携の概念 ===")
print("実際のC言語連携では以下のような関数を定義できます:")
print("- C言語で高速な計算関数を実装")
print("- LuaからC関数を呼び出し")
print("- C言語からLuaスクリプトを実行")
print("- 共有ライブラリとしてC関数を提供")
-- Luaの限界をCで補完する例の説明
local function simulateCExtension()
print("\nC拡張の典型的な用途:")
print("1. 数値計算の高速化")
print("2. システムAPIへのアクセス")
print("3. 既存Cライブラリの活用")
print("4. メモリ集約的な処理")
print("5. リアルタイム処理")
end
simulateCExtension()
メリット・デメリット
メリット
- 軽量性: 非常に小さなメモリフットプリント(数十KB)
- 高いパフォーマンス: コンパクトながら高速実行
- 組み込み容易: C/C++アプリケーションへの組み込みが簡単
- シンプルな構文: 学習しやすく読みやすいコード
- 柔軟なデータ構造: テーブルによる配列・辞書・オブジェクトの統一
- メタプログラミング: メタテーブルによる強力な機能拡張
デメリット
- 限られたエコシステム: 標準ライブラリが最小限
- コミュニティサイズ: 他の主要言語と比較して小規模
- デバッグツール不足: 開発ツールやIDEサポートが限定的
- 1から始まる配列: 多くの言語と異なる配列インデックス
- グローバル変数問題: デフォルトでグローバルスコープになりやすい
- エラーメッセージ: 実行時エラーの詳細情報が限定的
主要リンク
公式ドキュメント
- Lua Official Site - Lua公式サイト
- Lua Reference Manual - 公式リファレンスマニュアル
- Programming in Lua - 公式プログラミングガイド
学習リソース
- Learn Lua in Y Minutes - クイックスタートガイド
- Lua Tutorial - 基本チュートリアル
- Lua Users Wiki - コミュニティWiki
開発ツール・ライブラリ
- LuaRocks - Luaパッケージマネージャー
- LÖVE 2D - Lua向けゲーム開発フレームワーク
- OpenResty - NginxでのLua活用
- Wireshark Lua - Wiresharkプロトコル解析
活用事例・フレームワーク
- Redis Lua Scripting - Redisでのスクリプト実行
- World of Warcraft Addons - WoWアドオン開発
- Kong API Gateway - Luaプラグイン
- Roblox Lua - ゲーム開発プラットフォーム