{}const=>[]async()letfn</>var
開発Lua

Luaのテーブル:初心者が過小評価している最も強力な構造

Luaの唯一のデータ構造であるテーブルが制限ではなくスーパーパワーである理由を理解しましょう。配列、辞書、オブジェクト、クラス、さらにはキューもすべてテーブルです。コード例、メタテーブル、典型的な初心者のミス、ミームなど。

К

Kodik

著者

4分で読める

Python や JS の後に Lua に来て、配列もオブジェクトも辞書もないことを知ったとき…テーブルだけです。

あなたの顔:😐

表の力を理解した一週間後の顔:🤯

Luaの表が「言語の貧困」ではなく、初心者が頑なに過小評価している優れたデザインである理由を理解しましょう。

ちょっと待ってください、本当に表だけですか?

はい。すべての場合に対応する単一のデータ構造。配列が欲しいですか?表です。辞書?表。メソッドを持つオブジェクトですか?そうです、テーブルです。キュー、スタック、グラフ、ツリー?すべてテーブルです。

プロジェクトのアーキテクチャを説明するLua開発者:

— ここには、テーブルを格納するテーブルのテーブルがあります。
— わかりました。ありがとうございます。

おかしな話に聞こえるかもしれませんが、実際には非常にエレガントです。

🔥 10万人以上の学生が参加中

理論を読むのに疲れた?
コーディングの時間だ!

Kodik — 実践でプログラミングを学ぶアプリ。AIメンター、インタラクティブなレッスン、実際のプロジェクト。

🤖 AI 24時間
🎓 修了証
💰 無料
🚀 始める
今日参加

配列としてのテーブル: 1からのインデックス付け(はい、単位から)

これが、普通の言語の世界から来た人にとっての最初のショックです。

local fruits = {"apple", "banana", "cherry"}

print(fruits[1])  -- "apple"
print(fruits[0])  -- nil 😭

1からのインデックス。ゼロからではありません。単位から。

かつてC言語を使っていた人は誰でも、この瞬間に身体的な痛みを感じるでしょう。しかし、Luaにはそれなりの理由があります。言語はプログラミングとは無関係な人々(エンジニア、デザイナー)向けに設計されており、彼らにとって「最初の要素= 1」は論理的です。

数日で慣れます。最初の2時間は苦しいです。

便利なクラシック:配列の反復処理

local heroes = {"Lua", "Python", "JavaScript"}

for i, name in ipairs(heroes) do
    print(i .. ". " .. name)
end
-- 1. Lua
-- 2. Python
-- 3. JavaScript

ipairs — 数値インデックスを順番にループします。それを覚えておいてください。どこにでもあります。

辞書としてのテーブル:ステロイドのキー値

ここからがマジックの始まりです。テーブルは、配列と辞書の両方にすることができます。

local player = {
    name = "ProGamer228",
    level = 42,
    hp = 100,
    "hidden achievement"  -- это индекс [1]
}

print(player.name)     -- "ProGamer228"
print(player["level"]) -- 42
print(player[1])       -- "hidden achievement"

2つのアクセス形式:ドット(player.name)と括弧(player["name"])を介して。キーが変数であるか、特殊文字が含まれている場合は、括弧が必要です。

local key = "hp"
print(player[key])  -- 100

-- Ключом может быть вообще что угодно
local weird = {}
weird[true] = "yes"
weird[3.14] = "pi"
weird[print] = "function as a key, why not"

キーは、nil 以外の任意のタイプにすることができます。これは驚くべき可能性を秘めていますが、乱用すべきではありません。コードの読みやすさも重要です。

表の長さ:ここではすべてが複雑です

オペレーター # は、テーブルの「配列」部分の長さを返します。

local t = {10, 20, 30, 40}
print(#t)  -- 4 ✅

local mixed = {10, 20, nil, 40}
print(# mixed)-- 2の場合もあれば、4の場合もあります🤡

重要なルール: 配列部分にnilがある場合、#の動作は定義されていません。Luaは任意の数値を返すことができます。これはバグではなく、設計上のものです。配列に穴を残さないでください。

辞書の単語数を正確に知りたいですか?手動でカウントしてください。

local function tableLength(t)
    local count = 0
    for _ in pairs(t) do
        count = count + 1
    end
    return count
end

オブジェクトとしての表:LuaのOOP

Luaにはクラスがありません。しかし、誰がそれを止めましたか?

local Dog = {}
Dog.__index = Dog

function Dog.new(name, breed)
    local self = setmetatable({}, Dog)
    self.name = name
    self.breed = breed
    return self
end

function Dog:bark()
    print(self.name .. " says: WOOF!")
end

function Dog:info()
    print(self.name .. " - breed: " .. self.breed)
end

local rex = Dog.new("Rex", "Shepherd")
rex:bark()  -- Рекс говорит: ГАВ!
rex:info()  -- Рекс — порода: Овчарка

メソッドを呼び出すときのドットの代わりにコロン(:)に注意してください。これは構文上の便利な機能であり、オブジェクトをselfとして自動的に渡します。これがなければ、rex.bark(rex)を書かなければならず、悲しいものになってしまいます。

継承も表を介して

local Puppy = setmetatable({}, {__index = Dog})
Puppy.__index = Puppy

function Puppy.new(name, breed, toy)
    local self = Dog.new(name, breed)
    setmetatable(self, Puppy)
    self.toy = toy
    return self
end

function Puppy:play()
    print(self.name .. " plays with " .. self.toy .. "!")
end

local baby = Puppy.new("Bobik", "Corgi", "ball")
baby:bark()  -- Бобик говорит: ГАВ! (унаследовано от Dog)
baby:play()  -- Бобик играет с мячиком!

メタテーブルと __index は、Lua オブジェクト システムの心臓部です。現在のテーブルでフィールドが見つからない場合、Luaはメタテーブルの__indexを調べます。チェーンは任意の長さにすることができます。これが継承です。

メタメソッド:すべてをオーバーロードします

メタテーブルを使用すると、標準操作のテーブルの動作を上書きできます。

local Vector = {}
Vector.__index = Vector

function Vector.new(x, y)
    return setmetatable({x = x, y = y}, Vector)
end

-- Перегружаем оператор сложения
function Vector.__add(a, b)
    return Vector.new(a.x + b.x, a.y + b.y)
end

-- Перегружаем вывод через tostring
function Vector.__tostring(v)
    return "(" .. v.x .. ", " .. v.y .. ")"
end

local v1 = Vector.new(1, 2)
local v2 = Vector.new(3, 4)
local v3 = v1 + v2

print(tostring(v3))  -- (4, 6)

知っておくべき主なメタメソッド:

  • __add, __sub, __mul, __div — 算数

  • __eq, __lt, __le — 比較

  • __tostring — 文字列表現

  • __index —存在しないフィールドへのアクセス

  • __newindex — 新しいフィールドの記録

  • __call — 関数としてのテーブルの呼び出し

  • __len — オペレーターの再定義 #

__call を使用すると、呼び出し可能なテーブルを作成できます。これは実際に本番環境で使用されています。

local Logger = setmetatable({}, {
    __call = function(self, message)
        print("[LOG] " .. os.date("%H:%M:%S") .. " — " .. message)
    end
})

Logger("Server is running")  -- [LOG] 14:32:01 — Сервер запущен

実用的なパターン:実際のコードの表

表を介した設定

local config = {
    server = {
        host = "localhost",
        port = 8080,
    },
    database = {
        name = "myapp",
        user = "admin",
        password = "hunter2",  -- классика
    },
    debug = true,
}

print(config.server.port)  -- 8080

セット

local function Set(list)
    local set = {}
    for _, v in ipairs(list) do
        set[v] = true
    end
    return set
end

local langs = Set{"Lua", "Python", "JavaScript", "Lua"}

if langs["Lua"] then
    print("Lua in action!")  -- Lua в деле!
end

if not langs["COBOL"] then
    print("COBOL? No, we haven't heard of it")
end

キュー

local Queue = {}
Queue.__index = Queue

function Queue.new()
    return setmetatable({first = 1, last = 0}, Queue)
end

function Queue:push(value)
    self.last = self.last + 1
    self[self.last] = value
end

function Queue:pop()
    if self.first > self.last then return nil end
    local value = self[self.first]
    self[self.first] = nil
    self.first = self.first + 1
    return value
end

local q = Queue.new()
q:push("first")
q:push("second")
print(q:pop())  -- "first"
print(q:pop())  -- "second"

表を使用する初心者がよく犯す間違い

1. 表がリンクで送信されることを忘れる

local a = {1, 2, 3}
local b = a       -- b указывает на ту же таблицу!
b[1] = 999
print(a[1])       -- 999 (сюрприз!)

コピーが必要ですか?手動で作成してください:

local function shallowCopy(t)
    local copy = {}
    for k, v in pairs(t) do
        copy[k] = v
    end
    return copy
end

2. pairsとipairsを混同する

  • ipairs — 数値キーのみ、順番に、最初の nil で停止します

  • pairs — すべてのキー、順序は保証されません

3. 表を反復しながら表を変更する

そうしないでください。ただしないでください。変更を別の表に集めてから適用してください。

4. 穴のあるテーブルの場合、# を信頼できるものと見なす

すでに述べましたが、繰り返します。nil配列の中央に=予測できない長さ。オプションなし。

コディックと一緒にLuaや他の言語を学ぼう!

ここまで読まれたのであれば、理論だけでなく実践にも明らかに興味をお持ちのことと思います。Luaのテーブルは、記事を読むだけでなく、手でコードを書くときに最もよく理解されます。

コディック — プログラミングをゼロから学び、実践的な課題を通じてスキルを磨くことができるアプリケーションです。Python、JavaScript、HTML、CSSなどの技術は、単にコードを見るだけでなく、実際にコードを書くことに重点を置いています。

また、当社には テレグラムチャンネル 2000人以上の開発者のコミュニティで、役立つ投稿、タスクの分析、プログラミングに関するミーム(それらなしではどこにも行けません)が定期的に公開されます。待ち時間、移動中、昼食時など、便利な場所で資料を繰り返すのに最適な方法です。チャンネル登録して、毎日レベルアップしましょう。

まとめ:なぜ表は素晴らしいのか?

Luaのテーブルはスイスアーミーナイフのようなもので、最初は奇妙に思えるものの、その後はそれなしでどのように生活していたのかが理解できなくなります。10個のデータ構造の代わりに1つのデータ構造、最小限の構文、最大限の柔軟性。

覚えておくべきことは次のとおりです。

  • テーブルは、配列、辞書、オブジェクト、クラス、および一般的にすべてを置き換えます

  • 1からのインデックスはバグではなく機能です(ただ受け入れてください)

  • メタテーブルはテーブルを本格的なオブジェクトシステムに変換します

  • 表はリンクを介して転送されます。コピーには注意してください

  • #は、穴のない配列でのみ確実に動作します

Luaは、少ないほど良いと言うことを証明する言語です。そして、表はこの哲学の最良の例です。

さあ、Luaで何かを書いてみましょう。テーブルが待っています。 🚀

🎯先延ばしをやめよう

記事は気に入った?
実践の時間だ!

Kodikでは読むだけでなく、すぐにコードを書く。理論 + 実践 = 本当のスキル。

即座に実践
🧠AIがコードを説明
🏆修了証

登録不要 • カード不要