定数テーブルのフリーズ
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の列挙型が完成します。実行時には誰も改変できない名前付きの値が得られ、それらを使うあらゆる箇所で編集時の型チェックが行われます。
チャレンジ
簡単何も変更できない定数テーブルを作成します。
local Size = table.freeze({Small = 1, Medium = 2, Large = 3})を作成します。Size.Largeとtable.isfrozen(Size)を出力します。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入門のすべてのレッスン
8Enum、Luau流のアプローチ
LuauにおけるEnumパターンテーブルによる数値Enumユニオン型としての文字列EnumリテラルユニオンEnumの活用定数テーブルのフリーズまとめ:Enum、Luau流のアプローチ自分で練習してみよう: Luauオンラインコンパイラ