Menu
CoddyTech

定数テーブルのフリーズ

CoddyのLuaジャーニー「Luau入門」セクションの一部。レッスン 59/80。

定数テーブルには弱点があります。それでも普通のテーブルにすぎません。どこにあるどんなコードからでもUserRole.Admin = 99と書き込めてしまい、「定数」はいつの間にか定数ではなくなります。

Luauではtable.freezeを使って、この問題を解決できます。テーブルを凍結すると、実行時に読み取り専用になります。フィールドの追加、変更、削除を試みると、エラーが発生します。慣用的な書き方は、テーブルを作成したその場で凍結することです。table.freezeは同じテーブルを返すので、そのまま代入できます。

local Color = table.freeze({
    Red = 1,
    Green = 2,
    Blue = 3,
})

print(Color.Red) -- 1: 通常どおり読み取れる
Color.Gold = 4   -- ✗ エラー: 読み取り専用テーブルを変更しようとした

これまでこのコースで扱ってきたほかの機能と異なり、これは実行時の保護です。編集時の警告ではなく、書き込みが実行された瞬間に実際のエラーが発生します。型チェッカーが認識していないコードからの変更も防げます。

知っておくと便利な関連機能が2つあります。table.isfrozen(t)はテーブルが凍結されているかどうかを返します。また、凍結は浅いため、ネストされたテーブルは、それらも凍結しない限り変更できます。凍結を解除することもできません。一度凍結されたテーブルは、そのまま凍結された状態です。

凍結された定数テーブルと、パラメーターに使うリテラルユニオンを組み合わせれば、Luauの列挙型が完成します。実行時には誰も改変できない名前付きの値が得られ、それらを使うあらゆる箇所で編集時の型チェックが行われます。

challenge icon

チャレンジ

簡単

何も変更できない定数テーブルを作成します。

  1. local Size = table.freeze({Small = 1, Medium = 2, Large = 3})を作成します。
  2. Size.Largeとtable.isfrozen(Size)を出力します。
  3. pcall(function() Size.Huge = 4 end)をlocal okに格納し、okを出力します。

コードを実行を押します。出力には3、true、falseが表示されます。

自分で試してみよう

-- 1) local Size = table.freeze({...})
-- 2) Size.Large と table.isfrozen(Size) を print する
-- 3) 禁止された書き込みに対する pcall の戻り値を ok に格納し、それを出力する

Luau入門のすべてのレッスン

自分で練習してみよう: Luauオンラインコンパイラ