🌙

Lua 5.5(beta)の新機能紹介

に公開

2025/6/30に、Luaの最新バージョンであるLua 5.5のベータ版がリリースされました。

https://www.lua.org/work/#5.5.0

Lua 5.4.0から実に5年ぶりとなるマイナーバージョンのアップデートです。

Luaはマイナーバージョン間の互換性がないなかなかに終わっている言語なので、マイナーバージョンが上がる場合にはかなり大きな変更が行われます。
今どきLuaを好んで書いている人は少ないかも知れませんが、Luaの処理系実装をやっている身としては、Luaの最新情報は気になるところです。そして何より、Lua 5.5に関する日本語の情報が皆無...

というわけでこの記事では、Lua 5.5の新しい機能についてを紹介していきます。

globalキーワードの導入

  • declarations for global variables

グローバル変数の定義を明示するためのglobalキーワードが導入されました。

-- グローバル変数としてaを定義
global a = 0

-- 初期値を指定せずに宣言だけすることも可能
global b

-- 関数も明示的にglobalにできる
global function foo()
    print("foo")
end

local/globalを指定しないデフォルトの代入は、引き続きグローバル変数として扱われますが、スコープの冒頭でglobalキーワードを利用した場合、デフォルトのグローバル変数宣言は無効化されます。

X = 1         -- これはOK、グローバル変数として扱われる
do
    global Y  -- 明示的にYをglobalで宣言
    Y = 1     -- これはglobalとして扱われる
    X = 1     -- Xが宣言されていない(globalでの宣言が必要である)ためエラー
end
X = 2         -- スコープを抜けたので、デフォルトのグローバルが再度許可される

また、この変更によってLua 5.5ではglobalは予約語として扱われるようになりました。そのため、識別子としてglobalを使用することはできなくなります。

forループ変数の可変性

  • for-loop variables are read only

Lua 5.4以前では、forループ(generic for)の変数は書き換えが可能でした。

t = { 1, 2, 3 }

for i in pairs(t) do
    i = 10 -- 書き換えが可能
    print(i)
end

Lua 5.5では、forループで宣言される変数が読み取り専用になります。よって、上のコードはLua 5.5ではエラーになります。

浮動小数点数のprintを改善

  • floats are printed in decimal with enough digits to be read back correctly.

printで浮動小数点数を表示する際に、正確な値を読み取るのに十分な桁数で表示されるようになった...らしいです。

コンストラクタの改善

  • more levels for constructors

この説明では何が変わったのかが全くわからないので、Luaの中の人の例を引用すると、

return {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,{1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,{1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,{1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,{1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,{1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,{1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,}}}}}}}

このようなコードはLua 5.4以前ではfunction or expression too complex" or "function or expression needs too many registersのようなエラーが起こりますが、これがLua 5.5では動作するようになりました。必要なのかな、この修正

table.createの追加

  • table.create

標準ライブラリにtable.createが追加されました。シグネチャはtable.create (nseq [, nrec])で、事前に内部で割り当てられるバッファのサイズを指定してテーブルを作成することができるようになります。

local t = table.create(3)
t[1] = "a"
t[2] = "b"
t[3] = "c"

後から追加する要素が決まっている時の最適化に役立ちそうです。

utf8.offsetが文字の最後の位置を返すように

  • utf8.offset returns also final position of character

Lua 5.4ではutf8.offsetは指定された文字列(Luaでは1文字=1バイト)のn番目のバイト列の開始位置のオフセットを返しましたが、Lua 5.5ではこれに加えて終了位置のオフセットを2番目の戻り値として返すようになりました。

Lua外のunmanaged文字列を扱えるように

  • external strings (that use memory not managed by Lua)

C-APIから文字列を渡す際に、Lua外部で作成されたunmanagedな文字列を渡せるようになりました。これはlua_pushexternalstringで実現できます。

const char *(lua_pushexternalstring) (
    lua_State *L,
    const char *s, 
    size_t len,
    lua_Alloc falloc,
    void *ud);

luaL_openselectedlibsluaL_makeseedの追加

  • new functions luaL_openselectedlibs and luaL_makeseed

C-APIにluaL_openselectedlibsluaL_makeseedが追加されました。

void luaL_openselectedlibs (lua_State *L, int load, int preload);
unsigned int luaL_makeseed (lua_State *L);

luaL_openselectedlibsは選択したライブラリをロードするAPIです。ビットマスクでロードするライブラリを指定できます。

luaL_makeseedはシードとして利用可能な乱数を生成するAPIです。

その他の最適化

  • major collections done incrementally
  • more compact arrays (large arrays use about 60% less memory)
  • lua.c loads 'readline' dynamically
  • static (fixed) binaries (when loading a binary chunk in memory, Lua can reuse its original memory in some of the internal structures)
  • dump and undump reuse all strings
  • auxiliary buffer reuses buffer when it creates final string

そのほかにも、メモリ周りの最適化が結構行われているようです。

まとめ

色々と細かい変更が入っていますが、個人的に一番大きいのはglobalキーワードの導入でしょうか。意図せずグローバル変数を汚染してしまうことが多いので、これを明示できるようになったのはありがたいです。まあLuaを使う場面ではバージョンが固定されていることが多いので、使えるようになるのかは怪しいですが...

ということで、新機能の紹介は以上です。ありがとうございました。

Discussion