この初版は Lua 5.0 向けに書かれました。あとから出たバージョンでほとんど関連性は持っていますが、違う点もあります。
第 4 版は Lua 5.3 を対象にしており、Amazon やその他の書店で販売しています。
本を購入していただくと、Lua プロジェクトをサポートするのにも役立ちます。
![]() |
Lua でプログラムを組むLua | ![]() |
第 I 部. 言語 第 7 章. 反復処理と汎用の for |
反復処理では、単一の不変状態と制御変数に収まるより多くのステートを保持する必要があることがよくあります。最も簡単な解決策は、クロージャーを使用することです。別の解決策は、必要なものをすべてテーブルに詰め込んで、そのテーブルを反復処理の不変状態として使用することです。テーブルを使用すると、反復処理では必要な量のデータをすべて保持できます。さらに、データを反復中に変更できます。ステートは常に同じテーブル(したがって不変)ですが、テーブルの内容は反復中に変化します。このような反復処理では、すべてのデータがステートにあるため、通常は汎用の for で提供される 2 番目の引数(反復処理変数)は破棄されます。
このテクニックの例として、現在の入力ファイルからすべての単語を走査する反復処理 allwords
を書き換えます。今回は、line
と pos
という 2 つのフィールドを含むテーブルを使用してステートを保持します。
反復処理を開始する関数は単純です。反復処理関数と初期ステートを返す必要があります。
local iterator -- to be defined later function allwords () local state = {line = io.read(), pos = 1} return iterator, state end
iterator
関数は実際の処理を行います。function iterator (state) while state.line do -- repeat while there are lines -- search for next word local s, e = string.find(state.line, "%w+", state.pos) if s then -- found a word? -- update next position (after this word) state.pos = e + 1 return string.sub(state.line, s, e) else -- word not found state.line = io.read() -- try next line... state.pos = 1 -- ... from first position end end return nil -- no more lines: end loop end
できれば、状態をすべて for 変数に保持するステートレスな反復処理を書く必要があります。これらを使用すると、ループを開始するときに新しいオブジェクトを作成しません。反復処理がこのモデルに収まらない場合は、クロージャーを試す必要があります。さらにエレガントであることに加えて、通常、クロージャーはテーブルを使用する反復処理よりも効率的です。まず、クロージャーを作成する方がテーブルを作成するよりも安価です。2 番目に、アップバリューへのアクセスは、テーブルフィールドへのアクセスよりも高速です。後で、コルーチンを使用して反復処理を記述する別の方法を確認します。これは最も強力な解決策ですが、少しコストがかかります。
Copyright © 2003–2004 Roberto Ierusalimschy. All rights reserved. |
![]() |