この初版は 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. |
![]() |