--- Lua言語の手引き --- draft 2010 March


Lua言語の手引き

― プログラミング言語Lua(5.1)についての基礎知識 TeCGraf, PUC-Rio 訳2001年10月24日 改定2010年3月

1. はじめに

この文章は、プログラム言語Luaの解説として、Luaのホームページから配布されていたポルトガル語の入門書を和訳し、さらにバージョン5.1に対応したものです。Anna Magdalena Hester による文書をもとに Robert de Beauclair Seixas によってバージョン3.1の時に作成されたもので、Waldemar Celes Son、 Luiz Enrique de Figueiredo、 Robert Ierusalimschy による論文"Programming in Lua - Practical Theory (version 2.1) " および "The Language of Extension Lua "の内容を含んでいます。 この文書は、池田 徹志さん(大阪大学大学院)、阿部 幸絵さん(産業技術総合研究所)のご協力により上野 豊(産業技術総合研究所)が編集しました。

ftp://ftp.tecgraf.puc-rio.br/pub/lua/nocoes-3.1.pdf
http://www.tecgraf.puc-rio.br/lua/ftp/nocoes-3.1.pdf

Luaはフリーソフトウエアとして配布されているプログラミング言語ですが、 TeCGrafが著作権を保持しています。

ftp://ftp.tecgraf.puc-rio.br/pub/lua/lua-3.1.tar.gz
http://www.tecgraf.puc-rio.br/lua/


Copyright (c) 1994-1998 TeCGraf, PUC-Rio. Written by Waldemar Celes Filho, Roberto Ierusalimschy, Luiz Henrique de Figueiredo. All rights reserved.


2. 概要

Lua言語は、C 言語などで書かれたアプリケーションプログラムに組み込んで、 初期設定や機能拡張を実現するために開発されたプログラミング言語です。ア プリケーションプログラムに、Lua言語の処理系を組み込むことで、パラメー タ設定やカスタマイズした処理をLua言語で記述することができます。また、 単独で動作するLua言語インタプリタを使って、目的の処理を行うプログラ ムを作成することもできます。
Lua言語は、いわゆる関数型のプログラム言語で、処理の流れは、Pascal言語に似た簡素な文法になってい ます(if-elseif-else-end, while-do-end, repeat-until)。そして、データ記述方法が豊富で、便利な機能があります。
(1)文字列データの処理を容易にするパターンマッチング
(2)テーブル型データによる構造化したデータの記述
(3)テーブル内容の動的な変更が可能
(4)自動メモリ割り当てとガベージコレクション
メ モリの再配置や初期化などは言語処理系の持つガーベジコレクション機能によっ て、メモリや変数の定義などに煩わされることなく、 多様に構造化したデータを扱うプログラミングができます。テーブル型データは、デー タを抽象化するのに便利です。Lua言語のプログラミングでは標準関 数やその他のライブラリ関数が利用できますが、独自の関数を追加すること もできます。 これまでにLua言語を使ったシステムもいくつか開発されています。例えばCGILua は、高度なWebサイトを構築できるシステムですが、Lua言語によるスクリプトを使って、動的なHTML文書を生成できるようになっています。


http://www.lua.org


3. プログラムと実行環境

Lua言語のプログラムは、命令文と関数の定義で構成されます。それらは一つ の実行環境の中に作成されます。命令文はテキスト中のどのカラムにあってもよく、フリーな書式で、スペースや改行で区切ったり、セミコロン ( ;) で明示的に区切ったりすることもできます。また、2つの連続したハイフン ( -) から行末までがコメントとなります。

Lua言語のインタプリタは、一つの実行環境に複数のプログラムを読み込むことができ、それぞれのプログラムは、読み込まれた順に翻訳され、それぞ れの命令文が実行されます。そして、関数定義の中にある命令文は翻訳されたあと、関数のコードとして登録されます。また、大域変数や関数の登録されている実行環境は、インタプリタを動作させたときに作られ、利用を終了するまで有効で、それらの関数やデータは、Lua言語のプログラムやC 言語とのインターフェイ スのライブラリで、操作できます。

Lua言語の処理系では、実行単位のプログラムをチャンクと呼びますが、それ を仮想マシンの実行コードに翻訳し、その後仮想マシンによってコードを実行 します。登録されている関数のコードは、関数が呼び出された時に高速に実行されます。これは、コンパイラとインタプリタを融合した方式で、 プログラムを逐次翻訳することで実行速度を低下させることなく、イン タプリタの使いやすい環境を保っています。


4. 変数と型

Luaのプログラムでは、大域変数は宣言なしで使うことができます。(注:後で説明する局所変数を使うこともできます)例えば、次の文で、新たに変数 a を使い、2.3という数値型のデータを参照するようにします。
    a = 2.3
そして次の例では変数aで文字列データを参照するように変更します。

a = "Language Lua"

Lua言語では、変数には型がありませんが、変数で参照するデータの種類には型があり、 nil, 数値, 文字列, 関数, C の関数, ユーザデータ、 テーブルの7種類あります。

nil 型

nil型は 未定義データを表します。
a = b

この場合は、変数 b の参照するデータは nil となるので、変数 a には nil が代入されます。次の例のように、 nil とい う予約語で表現することができます。

a = nil

変数 a には nil という値が代入されますが、 a に値が入っ ていない状態と同じです。変数に値が入っていないかどうかは次のようにテス トすることができます。したがって、すべての未定義の変数は nil と いう値を持つと考えられます。

a == nil

数値型

Lua で扱う数値データは実数と整数の区別はありません。次の例では、 a、 b、 c、d の各変数に数値を代入しています。

a = 4
b = 4.0
c = 0.4e1
d = 40e-1

文字列型

Lua の文字列は一重引用符(' ')または二重引用符(" ")で囲まれる文字の系列 です。文字列中では、 以下のエスケープシーケンスを用いることができます。
    \n  改行
    \t  水平タブ
    \r  復帰
    \v  垂直タブ
    \xxx  文字コードが 10 進数 xxx の文字
    \a  ベル
    \b  一文字後退
    \f  フォームフィード
    \\  バックスラッシュ
    \"  二重引用符 (")
    \'  一重引用符 (')
    \\  バックスラッシュ(\)
二重引用符で囲まれた文字列中では、一重引用符をエスケープ無 しでそのまま用いることができます。しかし、ある文字列を囲むのに用いられ ている引用符合をその文字列中で用いるときには、エスケープする必要があり ます。次の二つは文字列として有効であり、同一の文字列です。
    s = "Olho d'agua"
    s = 'Olho d\'agua'
二重の角括弧も文字列を囲むのに用いられます。二重引用符や一重引用符と異 なり、この中ではエスケープシーケンスが解釈されません。また、それが入れ子になる場合は、角括弧の間に=を入れて、[=[ ]=] のように明示します。 例:
    s = [[ This is a text
    that crosses
    a string more than and contains one
    string nested: [=[nested]=] in the end!]]

関数

Lua の関数はファーストクラスの型と呼ばれますが、これは関数を変数に代入したり、 他の関数へ引数として渡したり、戻り値として返したりできるということです。 関数の定義とは、関数として働くプログラムが作られて、それがその名前の大域変数に代入されることです(6参照)。代入された大域変数は関数型 の値を持ちます。関数定義は次のような書き方になります。変数 func1に関数型の値が代入されることになります。
    function func1 (...)
    ...
    end
これは次のような関数呼び出しを行うことで実行できます。
    func1(...)

ユーザデータ

ユーザデータ型を用いることで、 C 言語の変数を Lua の変数に代入できます。 ユーザデータ型は C 言語の void * 型に相当し、C 言語の変数を Lua の変数で扱うことができます。代入と等価性の判定 以外の演算以外は行うことができませんが、 Lua言語 と C を結合するプログ ラムを書くのに便利です。しかし、Lua 言語のみでプログラムを書く時には用いるこ とはできませんし、Lua言語 中でこの型の値を直接生成することもできません。

テーブル

テーブル型は Lua における主要な型です。テーブル型は連想配列を実現して おり、nil 以外の他の任意の型のインデクスを用いることができます。 テーブル型を用いることで、ベクトル、リスト、レコード等の型を同一の構造 で作成できます。テーブル生成の構文を説明する前に1つ例を示します。以下は空のテーブルを明示的に作成して a に代入します。
    a = {}
このテーブルに後からフィールドを追加することも可能です。 テーブルに関しては7節で詳述します。

5. 代入と演算

前述のように Lua の変数は型を持たず、変数はいろいろな型の値を保持します。Lua の変数は動的に型づけされ、値が変数に代入される時 に特定の1つの型を持ちます。同じ変数に別の値が代入されれば、変数は2 度目に代入された値を持ちます。したがって2度目の代入の前には、 その変数はある1つの型を持っていますが、代入の後には別の型の値を持っ ていることがあります。変数が持つ値に演算を行うとき、その値が行う演算に 有効なものであるかどうかは実行時にチェックされます。例えば関数を値とし て持つ変数に加算を行おうとした場合には、実行時エラーになります(脚注 2)。

−代入と多重代入−

前節では簡単な代入の例を示しました。Lua では多重代入も可能で、 1回の代入で2つの異なる代入操作をすることができます。
    s, v = "Language Lua", 2
この例は、変数sに "Language Lua" という文字列を代入し、変数vに 2 という数値を代入します。

また、左辺の変数の数が右辺の値の数と異なることもあります。その場合には 左辺の変数に nil が入れられるか、右辺の値が捨てられます。

    a, b = 2
    c, d = 2, 4, 6
この例では a に 2、 b に nil が代入されます。 また c には 2、 d には 4 が代入され、6 という値は捨てられます。多重代入を利用することで、変数の値の交換を1つの命令で書くことがで きます。
    a, b = b, a
この例では a が持っていた値が b に、 b が持っていた値 が a に代入されます。よって、一時的な変数を用意する必要はありません。 (脚注2: この振舞いはタグ関数を用いることで変えることができる。 Lua 参照マニュアルを参照。)

−演算子−

Lua言語には、算術演算子、関係演算子、論理演算子、文字列を連結する演算子があり、ま演算が行われるときに、できるだけ自動的に型変換されます。

○算術演算子

Lua には一般の算術演算子があります。2項演算子には + (加算)、 - (減算)、 *(積算)、 / (除算)があります。また符合反転の - があります。 バージョン5からは剰余演算子として %が使われるようになりました。演算順序を変えるため、括弧を使うことができます。 以下は正しい式の例です。
    a = 2 * 3.4
    b = (a + 1) / 3.4
    c = 2 * (-3)
算術演算子は数値型の値にのみ使用できます(数値型に変換可能な文字列に対しても可能です。"自動的な変換" の節を参照)。演算子 ^ は通常は巾乗で、Lua 言語の数学関数ライブラリが使われます。この2項演算子 ^ は高い優先順位で処理されますが、内部的には、タグ関数を使って実装されています(Lua 参照マニュアル参照)。

○関係演算子

Lua には以下の関係演算子があります。
    <     小さい
    >     大きい
    <=    小さいか等しい
    >=    大きいか等しい
    ==    等しい
    ~=    異なる
関係演算子は、結果が偽の時 nil を返し、真の時 1 を返します。
    a = 4 < 3
    b = 4 > 3
この例では a に nil が代入され、 b に 1 が代入されま す。演算子 >,<,>=,<= は数値型または文字列型の値で使用でき、真偽の判断を行います。 そして、それはタグ関数を使うことで変更できます (Lua 参照マニュアルを参照)。 等価演算子 (==) は、はじめに比較される値の型が等しいかを調べ、 異なる場合には nil を返します。型が同じ場合には、値が等しいか を調べます。 数値や文字列の等しさは通常の基準で判断されます。 テーブル、関数、ユーザデータは参照が比較されます。 例えば2つのテーブルの場合、その2つのテーブルが同一の対象であ るかどうかで判断されるので、同じ要素を持っているかどうかでは判断されません。 非等価演算子 (~=) は等価演算子の逆です。

○論理演算子

論理演算子は”かつ”、”または”、”でない”の3つです。
    and        かつ
    or         または
    not        でない
and や or が複数ある場合には、左から右に評価されるので、全ての演算が評価される前に、式の値が決まってしまうことがあります。
    a =  23
    b = 15
    c = a < 20 or  b > a
    d = a < 20 and b > a
この例では、 c と d は nil になります。 d の場合、まず a<20 が偽となり、論理演算子 and によって結合されているので、b>a を評価する必要はなく、この式に偽になります。

○連結演算子


2つの文字列を連結する演算子は、Lua では2つのピリオド( ..) で 表されます。連結演算子は2つの文字列を連結した文字列を返します。
    a = "Language"
    b = "Lua"
    c = a .. " " .. b
この例では a の値に1文字空白が続き、b の値がつながったもの、つまり "Language Lua" という文字列が変数 c に代入され ます。

自動的な型の調整(coersion)

Lua では自動的に型の変換が行われることがあります。 文字列に算術演算子が使用されていて、その文字列が数値の場合、数値型への変換がされて演算されますが、変換できなければ、実行時エラーとなります。
    b = "53"
    c = 2 + b
この例では文字列 "53" は演算の前に数値に変換され、 c には 55 が 代入されます(変数 b は文字列型の値を持ったままです)。 他方で、文字列が必要な文脈で数値を使った場合には(連結演算子など)、 数値は対応する文字列に変換されます。 数値が完全なものであれば、小数や指数は点なしの文字列になります。 数値が分数を含む場合には、小数や指数を含むことがあります(脚注3)。 例えば、
    print("result: " .. 23)
は次のように出力されます。
    result: 23.
tonumber というLua言語の標準関数は、可能な場合は文字列を数値型に変換します。数値を文字列に変換するには、 必要に応じて tostring 関数を使うことができます(9参照、 sprintf で %.16g の書式で変換します)。 複数の演算子が使われている場合は優先順位があり、次の順に演算されます。また括弧を用いて演算順序を変えるこ とができます。
    ^
    not -(単項)
    * /
    + -..
    < > <= ~= ==
    and or


6. 流れの制御と局所変数

Lua にはプログラム言語として一般的な処理制御の機能があり、一群の命令をまとめたり、さらに何回も実行することを指定できます。また、宣言されたブロック中のみで有効な局所変数の宣言をする こともできます。
条件文 ( if )

Lua の基本的な条件文は if です。 if 文の形式は次のようにな ります。
    if exp then
        ブロック
    end
または、
    if exp then
ブロック1
else
ブロック2
end
または、
    if exp1 then
        ブロック1
    elseif exp2 then
        ブロック2
        ...
    elseif expN then
        ブロック N
    else
        ブロック N+1
    end
はじめの形式では、式 exp が nil でない値の場合にブロックが実行されま す。2番目の形式では、式 exp が nil の場合にブロック 2 が実行され、 そうでなければブロック 1 が実行されます。 3番目の形式では、多くの条件にもとづいてif-then-elseif-then- ... -else-end で条件判断する列を示しました。 上記の例では、式 exp1 が真ならば( nil で無いならば)ブロック 1 が実行 され、式 exp2 が真ならばブロック 2 が実行され、全ての式が偽ならば ( nil と等しいならば) ブロックN+1 が実行されます。

回数を指定した繰り返し (for)

Lua には繰り返しを記述するのに3種類の命令があります。 for,while と repeat です。 頻繁に利用されるのが回数を指定した繰り返しです。
    for i=1,n do
        ブロック
    end
変数 iは新しく作成され、1、からnまで1ずつ増分します。増分を変更したり、初期値を変更する場合の一般的な形式は次のようになります。
    for i=s,n,d do
        ブロック
    end
例として、nの階乗を計算するプログラムは次のようになります。
    f = 1     ----  0の階乗
    for i =1,n do
        f = f * i
    end
ここで使う繰り返し数の変数は、繰り返しブロックの中だけで有効なことに注意してください。後に述べるローカル変数です。endの後で参照しても繰り返しの最大数は入っていません。

最初に条件式がある繰り返し (while)

基本な繰り返し処理の一つである while では繰り返しの中身を実行するかどうかの 判断が先頭でなされます。一般的な形式は次のようになります。
    while expr do
        ブロック
    end
式 expr が真である間( nil でない間)、ブロック内の命令が実行 されます。例として、変数 n の階乗を計算する次のプログラムを 示します。
    f = 1     ----  0 の階乗
    i = n     ----- 繰り返しを制御する変数
    while i > 0 do
        f = f * i
        i = i - 1
    end
繰り返しを実行し終えた後には、 f は n の階乗の値を持ち、 i は 0 になります(繰り返しの終了条件)。

最後に条件式がある繰り返し (repeat)

繰り返しの中身を実行するかどうかの判断を最後に行うのが repeat て す。一般的な形式は次のようになります。
    repeat
        ブロック
    until expr
repeat では、ブロック内の命令は最低でも1回実行されます (繰り返しを実行するかどうかの判断は繰り返しの最後でしか行われません)。 また式 expr が真である間、繰り返されます。 上記と同じ階乗の計算を行うプログラムは次のようになります。
    f = 1   --- 1の階乗
    i = 1   --- 繰り返しの制御変数
    repeat
        f = f * i
        i = i + 1
    until i > n

関数による繰り返し (for)

繰り返しのたびに次の条件を計算する関数を使うために、イテレータ関数を使うことができます。関数については後に述べます。
    for i ,data in iterator() do
        ブロック
    end
iterator() に関数を指定します。例として、イテレータ関数pairs()を使って後に述べるデータ構造としてのテーブルの内容を順番にすべて取り出すことができます。
    for key,value in pairs(table) do
        print(key,value)
    end
この構文は複雑なデータ構造にうまく対処できるものです。

繰り返しの中断(break)

繰り返しの途中で、ある条件になった際にbreakを使って繰り返しを終了させることができます。breakは、ブロックの末尾にだけ指定できます。
    while true do
        if(expr) then break end
    end
もしどのような条件でもbreakをさせたいときは
do break end
のようにしてbreakだけのブロックを指定します。

局所変数の宣言


Lua では変数が局所的であることを宣言して使用します。 この局所変数の宣言はブロック内の系列の任意の位置に書くことができ、 宣言されたブロックが終わると変数も無効になります。 大域変数と同じ名前の局所変数を宣言すると、一時的に大域変数を隠します (局所変数が宣言されたブロック内で)。 プログラム中にその変数名が現れた場合には、局所変数として扱われます。 局所変数の宣言時の初期化は次のような構文になります。 例として以下のプログラムを示します。
    a = 2               --- 大域変数に2を代入
if a > 0 then
local b=a --- a の値(2)を初期値として局所変数 b を宣言
a=a+1 --- 大域変数 a に 1 を加える
local a=b --- b の値を初期値として局所変数 a を宣言
print(a) --- 局所変数 a の値(2)を表示 end --- 局所変数 a, b の有効範囲はここまで
print(a) --- 大域変数 a の値(3)を表示
1つの命令で複数の局所変数を宣言して初期化することもできます。
    local  a, b, c = 2, 5+6, -3
この例では、 a は 2 を初期値とし、 b は 11 を、 c は -3 をそれぞれ初期値としています。初期化されない局所変数の値は nil とな ります。

7. 関数

Lua では関数はファーストクラスの型として扱われます。つまり、関数は変数 に代入したり、他の関数に引数として渡したり、戻り値として返したりするこ とができます。 関数を定義する時には、関数の名前を持つ大域変数に関数の機能を実現するプ ログラムを代入します。Lua の関数は大域環境中の任意の場所で定義できます。関数の定義の一般的な形式は次のようになります。
    function name ([ 引数のリスト ])
        命令のブロック
    end
ここで name は関数が代入される大域変数の名前です。引数のリストは 関数内の局所変数と同様に扱われ、関数呼び出しの時の引数で初期化されます。 関数呼び出しの一般的な形式は次のようになります。
    name ([ 引数のリスト ])
関数名の後に括弧で囲まれた0個以上の引数のリストを続けて書きます。 name が関数を値として持たない場合(関数型の値では無い場合)には 実行時エラーになります(タグ関数参照)。引数が指定された場合には、 まず引数は関数呼び出しの前に評価されます。次に関数定義に指定された仮引 数と、関数呼び出しに指定された実引数との間で対応が取られます (この時に多重代入と同様な調整が行われて対応が決まります)。

Lua では引数は値渡し(by value)で渡されます。したがって、関数が呼び出さ れた時点での実引数の値が、関数の仮引数の値にコピーされて関数内の局所変 数になります。関数の呼び出し元では、引数に指定した変数の値は呼び出し時 のままで変わりません。

Lua の関数は 0個、1個、またはそれ以上の値を return 命令によって 返すことができます。よって、関数呼び出しの時に変数への参照を引数として 渡す必要がありません。関数の実行中に return 命令が現れると、関数 の実行は終了して関数が呼び出された位置の次に制御が戻ります。 return 命令の後には0個以上の式のリストを書くことができます。一般的 の形式は次のようになります。
    return [ 式のリスト ]
構文規則上、 return 命令はブロックの最後でなければなりません。 このことにより、 return 命令の後に置かれて決して実行されない 隠れた命令を防ぐことができます。 return 文がブロックの最後でない場合には、文法エラーになります。

関数の戻り値は、関数呼び出しの時に書かれた変数リストに合わせて調整され ます。例として、座標 (x,y) を更新する次の関数を示します。
    function translate (x, y, dx, dy)
        return x+dx, y+dy
    end
次のように関数呼び出しが行われたとすると、
    a,b = translate(20, 30, 1, 2)
a には 21 (=20+1) が代入され、 b には 32 (=30+2) が代入されます。 次のような関数呼び出しの場合には、
    a = translate(20, 30, 1, 2)
関数の(2つ目の)戻り値は捨てられ、21 を受け取ります。次のような呼び出 しの場合には、
    a, b, c = translate(20, 30, 1,2)
a には 21 が代入され、 b には 32 が代入され、 c には nil が代入されます。

複数の値を返す関数呼び出しは値のリストと同一に扱われるわけではありませ ん。多重代入で調整が行われる時には、1つ目の戻り値だけが考慮されます。 例として、少しに異なる2つの例を挙げます。はじめに、次の関数呼び出しの 場合には、

    a, b, c = 10, translate(20, 30, 1, 2)
a には 10 が代入され、 b には 21 が代入され、 c には 32 が代入されます。 このように関数呼び出しがリストの最後の場合には、関数呼び出しが1つずら されます。しかし、次の呼び出しでは、
    a, b, c = translate(20, 30, 1, 2), 10
驚くかもしれませんが、関数が返す値の個数によらず1つ目の返り値だけが 扱われ(この場合21)、もう1つの返り値の 32 は捨てられます。よって、 a には 21 が代入され、b には 10 が代入され、cにはnilが代入されます。

Lua では可変個の引数を受け取る関数を定義することができ、これは関数 定義の引数リストの最後にピリオドを3つ ( ...) つけることで表せます。この形式の関数では実引数と仮引数の対応づけだけで調整は行われません。関数の中では、3つのピリオドをローカル変数に代入すれば、 引数リストに指定されたものを参照することができます。あるいは、関数の引数としてそのまま渡すこともできます。例として、2つの異なる関数定義をします。

    function f(a, b) end
    function g(a, b, ...) end
これらの関数呼び出しでは、実引数と仮引数との間で次のような対応づけが行なわれています。
    実引数          仮引数
    f(3)            a=3, b=nil
    f(3, 4)         a=3, b=4
    f(3, 4, 5)      a=3, b=4
    g(3)            a=3, b=nil, arg={ n=0 }
    g(3, 4)         a=3, b=4, arg={ n=0 }
    g(3, 4, 5, 8)   a=3, b=4, arg={ 5,8; n=2 }

8. テーブル型と連想配列


Lua のテーブルは連想配列であり、数値や文字列などの nil を除く任 意の型の値をインデクスとすることができます。テーブルのこの柔軟性は、 Lua 中のオブジェクトの記述の基礎になっています。

テーブルの作成


テーブルは使う前に明示的に作成する必要があり、 { }で初期化を行います。次は空のテーブルを作成し、 t という変数に代入する例です。
t = { } これにより、変数 t はテーブル型の値を持ちます。 代入の例は次のようになります。
    t[1] = 13
    t[45]=56
テーブルのインデクスの値に上限はなく、テーブルの次元は必要に応じ て自動的に変更されます。また、次のように書くこともできます。
    t["name"] = t[1] + 2
name という文字列のインデクスに対応するテーブル中の値として、 インデクス 1に対応する値(ここでは 13)に 2 を加えた値を代入します。よっ てインデクス"name" に対応する値は 15 になります。 また以下のように書くこともできます。
    t[t] = 5
これは t というテーブル型のインデクスに対応する値として 5 を代入し ています。テーブル t はインデクスとして有効な値です (一見混乱しているように見えますが、やっていることは間違っていません)。

また文字列をインデクスにするときには、ピリオドを使った記法を用いること ができます。例えば、

    t["version"]=4
これは以下と等価です。
    t.version = 4
この記法の方が判りやすくなります。 ただし、文字列がスペースを含むときはピリオドを使った表記を用いることはできません。
例:    t["Rio De Janeiro "]=1994
数値と同様に、任意の型の値をテーブルに代入することができます。 次に示すのは、テーブルt への正しい代入の例です。
    t[10] = "example"
    t[2.34] = 12
    t.tabela, t[0] = 3, 12
    t[-234] = 0
    a = "Lua"
    t[a] = 5
最後の例は注意深く見る必要があります。 a は "Lua" という値を 持つ変数と考えると、これは Lua というインデクスに対応する値として5 を代入していることになります。 しかし、t.a はt["a"] と 等価ですが、t[a] とは異なります。 ここでは t[a] と t.Lua が等価にになります。

インデクスに対応する値を一度も与えられていない(初期化されていない)テー ブル中の値は nil になります。したがって上の例の代入だけを行った とすると、

    print(t[999])
999 というインデクスに対応する値は初期化されていないため、この命令は nil を出力します。

テーブル中に他のテーブルを代入することもできるので、多次元配列が実現で きます。例えば、次のようになります。

    m = { }
    m[1] = { }
    m[2] = { }
    m[1][1] = 1.0
    m[2][1] = 0.0
また次のように書くこともできます。
    s = { }
    s.dist = { }
    s.dist.name = "Language Lua"
    s.dist.version = 4

値を指定したテーブルの初期化


Lua ではテーブルの作成時に初期化することができます。 テーブルの初期化は次のように行うことができます。
    { 式1, 式2, ...., 式N }
このようにテーブルを作成する { } の間に式のリストを書きま す。リストの要素はそれぞれ評価され、1番目の値はインデクス 1 に対応づ けられ、2番目の値はインデクス 2 に、というぐあいになります。 したがって次の例は、
    t = {23, 45, -7, "Lua", 6+4}
以下と等価です。
    t = { }
    t[1] = 23
    t[2] = 45
    t[3] = -7
    t[4] = "Lua"
    t[5] = 6+4
初期化を行った後でも、テーブルに他の値を代入することはできます。 テーブルにはいつでも nil 以外の任意のインデクスに対応して任意の 値を代入することができます。例えば初期化の後に、次のような命令を実行す ることができます。
    t[67] = 0
    t["Lua"] = "example"

フィールドを指定したテーブルの初期化


Lua ではフィールドを指定してテーブルを初期化することもできます (訳注: インデクス i に対応する値を、テーブルのフィールド i とも呼びます)。 一般的な形式は次のようになります。
    { [ 式A ] = 式1, [ 式B ] = 式2... }
初期化の際に、インデクスと値の対であるフィールドを指定することができる。 テーブルのインデクスが文字列の場合は、次のように単純化することができます。
    string1 = expr1
よって次の例は、
    t={ name="Language Lua ", [1]=3.0, [f(x)]=g(y) }
以下と等価です。
    t={}
    t.name=" Language Lua "
    t[1]=3.0
    t.[f(x)]=g(y)
同様に、テーブルにはいつでも nil 以外の任意のインデクスに対応し て任意の値を代入することができます。例えば初期化の後に、次のようにする ことができます。
    t["Lua"]=" example "

両方の形式を混在させた初期化


これまでの2つの初期化の形式を組み合わせて使うことができます。 一般的な形式は次のようになります。
    table={ 式のリスト , フィールドのリスト }
フィールドのリストと式のリストを区別するためにセミコロンで分けていることもあります。これは、バージョン4までの制約だったからで、バージョン5では必要ありませんが、習慣的にそう書かれていることがあります。次の例は、
    t = { nome = "Linguagem Lua", [1] = 3.0, [f(x)] = g(y) }
    t = {23, 45, -7 ,
         nome="Linguagem Lua",
         versao=3.0,
         [4]=80
    }
以下と等価です。
    t = { }
    t[1] = 23
    t[2] = 45
    t[3] = -7
    t.nome = "Linguagem Lua"
    t.versao = 3.0
    t[4] = 80

9. エラーの制御


Luaでのエラーは、プログラムの翻訳時と実行時の2種類があります。通常は、コンパイル中や実行時にエラーが起こると、エラー処理関数が実行され、Lua を実行している関数 (lua_load, lua_call, など) は終了となり、エラーの状況が戻り値として返されます。このほかに、ある関数を実行する時に、エラーがあっても回復して他の処理をさせたい場合には、関数を保護モードで動作させます。pcall()関数をつかって関数を実行すると保護モードになります。エラーがなければ、戻り値としてtrueに続いてその関数の戻り値が得られ、エラーがあった場合には、falseとエラーメッセージ文字列となります。エラー処理関数は呼ばれないので、Luaの実行は継続できます。
エラー処理関数は、エラーとなったプログラムの行番号とその内容と表示し、それがどの関数から呼ばれてきたかを順番に調べるスタックトレースを表示します。エラー処理関数を変更するには、C言語APIを使いますが、Luaの中で一時的に変更する時には、xpcall()関数を使うこともできます。


10. 定義済みの関数


Luaのプログラミングに有用な部品は、標準関数として用意されています。これらの関数は実行環境が変わっても有効です。

loadfile(filename) filename 実行するファイル名

指定されたファイルをLua言語のプログラムとして実行できるようにした関数を作成します。文法エラーで実行できない場合は nil が返されます。戻り値で得られる関数を呼ぶとプログラムが実行されます。ファイル名を指定しないと、標準入力からのデータを読みます。

(例)
	dostring("bib.lua") then
	if not f then
        print("It is not possible to open the library of functions")
	end

loadstring( string [, name ] )

文字列をLua言語のプログラムとして実行できるようにした関数を作成します。この関数を呼ぶことでその内容が実行されます。文法エラーがある場合はnilとなります。

(例)botao1,botao2,...という名前のテーブルの内容を集約する。
	i = 1; botao = {}
	f = loadstring("return botao"..i )
	b=f()
	while b do
		botao[i] = b
		i = i + 1
		f = dostring("return botao"..i )
		b=f()
	end

next( table, index )

テーブルとそのインデクスを指定して、次の要素のインデクスと値を返します。indexにnilを指定すると、一番最初の要素のインデクスと値が得られます。これを使ってテーブルのすべての要素を列挙することができます。インデクスは数値の他に、文字列など他のデータ型を使うこともできます。戻り値は、インデクスと値の2つで、次の要素がなくなるとnilになります。Lua言語では、文字列のインデクスを使うときも宣言などは必要ありません。指定されたインデクスが存在しないときにはその値はnilという意味になりますが、next()では存在するものだけを順に得ることになります。要素の順番は、Luaによって管理されていて、作成した順ではありません。

(例)

テーブルtの内容をすべてプリントするには次のようにします。
field,value = next(t, nil)              --テーブルの最初の要素
while field do                          --存在するまで
print(field, "=", value) --内容を出力
field,value = next(t, field) --次の要素end

_G


大域変数をあらわすテーブルです。これをnext()関数に指定すれば大域変数をすべて列挙することができます。
name,value = nextvar(nil)               --先頭にある大域変数
while name do --nameが存在すれば
print(name, "=", value) --その内容を表示
name,value = nextvar(name) --次の大域変数 end

type( value )

引数に指定された対象の型を文字列で返します。戻り値は、"nil", "number", "string","boolean", "table", "function", "userdata" "thread",のどれです。

(例) t = {} print(type(2.4),type("Alo"),type(t),type(t[1]),type(print)) (結果) number string table nil function

tonumber( e [,base] )

文字列型になっている数字を数値データに変換します。変換できなかった時はnilを返します。10進数以外の時は、2番目のパラメータに2〜32の数値を指定します。
(例)
	print(tonumber("34.56 "), tonumber("3.2 X"), tonumber(2))

(結果)	34.56	nil	2

tostring( e )


数値データを文字列データに変換します。
(例)
	print(tostring(3.2), tostring({10,20,30}), tostring(print))

(結果)
	3.2	table: 0x324a43	function: 0x63ed21

print( expr1, expr2, ... )


与えられたデータを標準出力に出力します。出力の書式を整えるにはformat()関数を使います。
(例)
	print( 2*3+2 )
print( "valor = ", valor )

error( msg )


実行時エラーを生成し、与えられた文字列を標準出力に出力し、実行を中断します。

pcall( func, ... )


与えられた関数を、2番目以降の引数で実行します。関数の戻り値は、falseまたはtrueで、そのあとに関数の戻り値が追加されます。falseだった場合には、2番目の戻り値はエラーメッセージになります。
    a,b=pcall( patm.sin, 1.0 )
      --- b = 0.841709848079
    a,b = call( math.max, 1,4,5)
      --- b = 4
    a,b=pcall(math.sin,"@")
    print(a,b)
  false   bad argument #1 to '?' (number expected, got string)


assert( value [,message] )


引数で与えられたデータがnilならばエラーになり、2番目のパラメータに与えた文字列をプリントします。

(例)assert( readfrom(FILE),"cannot open" .. FILE )


11. ライブラリ関数

Luaでは、数学、文字列、ファイル入出力の3つの基本ライブラリ関数が用意されています。

文字列処理ライブラリ

文字キャラクタの列による文字列を扱う汎用の関数として、文字列の長さを調べたり、部分文字列をとったりする関数が使えます。
string.find( str, pattern [, init [, plain ]] )
文字列strの中に、patternで指定した文字列を探し、初めの場所と終わりの場所の2つの数値が戻り値になります。initで検索を始める最初の場所を指定できます。また、plainでnil以外だった場合は、パターンマッチングの機能を使わずに単純な文字列比較を行います。文字列が見つからなかった場合はnilが戻り値となります。パターンマッチにキャプチャを使った場合は、キャプチャに対応する文字列が戻り値に追加されます。
(例)
i, f = string.find("Linguagem Lua 3.0", "Lua")
print( i, f )
(結果)
 11 13

(例)
	data = "13/4/1997"
	i, f, day, month, year = string.find(data, "(%d*)/(%d*)/(%d*)")
	print( day,month, year )
(結果)
	13, 4, 1997

文字パターン

文字の種類で探すことができます。 >文字の種類を表現するために、以下のような文字パターンが使えます。

     x                  (x が ^$()%.[]*+-? のどの文字でもない場合) 文字 x そのものを表します。
     %x                xはアルファベットや数字以外の記号で、その記号自体を表します。特殊文字を表すのに使います。
     .                  すべての文字
     %a                 アルファベット文字
     %A                 アルファベット文字以外
     %d                 数値(10進数)
     %D                 数値以外
     %l                 アルファベット小文字
     %L                 アルファベット小文字以外
     %s                 空白文字(スペース、タブ、quebras de linha)
     %S                 空白文字以外
     %u                 アルファベット大文字
     %U                 アルファベット大文字以外
     %w                 文字と数字
     %W                 文字と数字以外
     [文字パターン列]   指定した文字のうちのどれか
     [^文字パターン列]  指定した文字のどれでもない

指定した文字パターンの繰り返しをあらわすために、 次の特殊文字が使われます。

特殊な文字パターン表現(ワイルドカード)

いくつかの文字パターンをつなぎ合わせてもかまいません。 パターン先頭の^ は対象文字列の先頭を意味します。 パターン最後の $ は対象文字列の 最後を意味します。パターン中の他の位置に置かれた場合は、^ や $ は特別な意味を持たず、それ自身を表します。

パターン中には括弧で囲まれたパターンが含まれている場合は、キャプチャと呼ばれます。マッチングが起こった場合には、キャプチャの部分にマッチした文字列は保存され、後で用いることができます。キャプチャは左括弧に対応する番号がつけられます。

例えば、"(a*(.)%w(%s *))"では、a*(.)%w(%s *)に合致する部分文字が第1番目のキャプチャになり、2番目に(.)に合致した一つの文字、%s *が3番目になります。

(例)

     function name (arg1,arg2)
     (function %s*(%a+)(%b())) 
 

によって、Lua言語の関数定義は関数の名前 (%a+)と、そのパラメータリスト(%b())をキャプチャとして得ます。

string.len( str )

文字列strの長さを戻り値として返します。 (例)print(string.len("Linguagem Lua"))(結果) 13.

string.sub( str, I [, j ] )

文字列strのl番目からj番目までの文字で新たに文字列データを作って返します。j がない場合は最後の文字までとなります。文字列の最後を −1として数えて、jに負の値を指定することもできます。例えば、string.sub(str, 1, j) の場合はj番目の文字までを返し、string.sub(str, i) はi番目から後の文字を返します。
(例)a = "Linguagem Lua"print(strsub(a, 11))
(結果)Lua.

string.lower( str )

文字列strを小文字にします。
(例)
	print(string.lower("Language Lua"))
(結果)
	language lua

string.upper( str )

文字列strを大文字にします。
(例)print(strupper("Linguagem Lua"))
(結果) LANGUAGE LUA.

string.rep( str, n )

文字列strをn回繰り返した文字列を作ります。
(例)print(strrep( "0123456789", 2 ))
(結果)01234567890123456789

string.char( str [, I] )

文字列strのl番目の文字のASCIIコードを返します。
(例)print(string.char("abc",2))
(結果) 42.

string.format( formatstring, exp1, exp2, ... )

文字列formatstringに従ってそれ以降のexp1,exp2,の値を指定した書式で文字列に変換します。書式は%に続けて表示の型を示すアルファベット文字をつけた形式でC言語におけるprintfとほぼ同じです。変換した文字列を戻り値として返します。
(例)   name = "Car"
             id = 123
             cmd = string.format( "insert into table (name, id) values (%s, %d)" , name, id )
SQLの挿入コマンド(insert)となる文字列を、テーブルのidと名前を使って作っている例です。
	print( string.format( "%c", 65 ) )
このようにして、データの文字を表すANSI(American NationalStandard Code for Information Interchange) のコード変換が可能です。
(例)a = 123.456
print( string.format( "%+010.2f", a ) )(結果)
 +000123.46.
     %s      文字列
     %q      引用符でかこんた文字列
     %c      文字
     %d      10進整数
     %u      符号なし整数
     %i   (同上)
     %o      8進整数
     %x      16進整数(abcdef)
     %X      16進整数(ABCDEF)
     %f      実数 [-]ddd.ddd
     %e      実数 [-]d.ddd e[+/-]ddd
     %g      実数 %fまたは %e
     %E      実数 %eと同じだが大文字のEを使う
     %%      %文字そのもの

書式制御のために、占める文字列の最小サイズを修飾子として%のあとに指定します(例: %10d)。負の値は、左づめを指定します。+を付けると数値の前に+か−を付けます。さらにピリオドに続けて、小数点以下の桁数を指定できます(例: %.2f)。 0を指定すると数値の左に0を追加します。

string.gsub( str, pattern, repl [, n ] )

文字列strからパターン文字列patternを探し、文字列replで置換します。replに関数を指定することもでき、関数を実行した結果で置換します。パターンはstrfindの時と同じで、パターンが見つかるごとに置換が行われますが、4番目に指定したnで置換回数の最大を指定できます。パターンがキャプチャを含んでいると、それらはrepl文字列中にある%1,%2に展開されます。replが関数の時は、キャプチャされた文字列が関数のパラメータとして渡されます。戻り値は、置換した文字列と、置換した回数です。
(例)print( gsub( "Linguagem Lua 3.0", " ", "+" ) )
(結果)
 Linguagem+Lua+3.0.
 ( 例2)texto = " Linguagem Lua 3.0 "print( gsub( texto, " *", " " ) )
 (結果2)置換は行われないので、"Linguagem Lua 3.0 ".
 (例3)キャプチャ機能
 
 lista = [[arq.txttexto.txtr.txt]]
 print( gsub( lista, "(.*)%.txt\n", "move %1.txt %1.bak\n" ))
 (結果)move arq.txt arq.bakmove texto.txt texto.bakmove r.txt r.bak

数学ライブラリ

数値データの最大値、最小値を得る関数では、可変個数の引数を使うことができます。

min( expr1, expr2, ..., exprN)
max( expr1, expr2, ..., exprN)

(例)print(min(23, 5, 123, 3))print(max(23, 5, 123, 3))(結果)
 3 123.

C 言語で利用されている数学関数ライブラリも利用できます。角度の単位はラジアンです(バージョン4までは度を使いました)。

     log(value)         logaritmo de value na base e
     log10(value)       logaritmo de value da base 10
     cos(angle)         cosseno de angle (especificado em graus)
     sin(angle)         seno de angle (especificado em graus)
     tan (angle)        tangente de angle (especificado em graus)
     acos(value)        arco cosseno, em graus, de value
     asin(value)        arco seno, em graus, de value
     atan(value)        arco tangente, em graus, de valuea
     tan2(y,x)          arco tangente, em graus, de y/x
     deg(angle)         converte angle (especificado em radianos) para graus
     rad(angle)         converte angle (especificado em graus) para radianos
     abs(value)         valor absoluto de value
     sqrt(value)        raiz quadrada de value
     ceil(value)        inteiro imediatamente inferior a value
     floor(value)       inteiro imediatamente superior a value
     mod(value,div)   divで割った余り
     random([[from,]to]) 乱数

入出力関数

ファイルや装置からのデータの入出力を行うためにオペレーティングシステムの機能を使うライブラリです。C言語と同様に、ファイルハンドルと呼ばれる変数でファイルを指定しますが、デフォルトの入力と出力の2つのファイルハンドルはファイルハンドルを省略することができます。C 言語での標準入出力である stdin、stdout、stderr は、ioテーブルのフィールドに定義されていて これを使うこともできます。初期状態では、io.stdinとio.stdoutが入力と出力に設定されています。

io.input( filename )

指定したファイルをデフォルトの読み取り用にオープンします。戻り値はファイルハンドルで、失敗したときはnilと、エラーメッセージの2つが得られます。filenameを指定しない時は、現在のファイルハンドルを返します。 (例) io.input( "c:\\txt\\b.txt" )

io.output( [filename ])

指定したファイルを書き込み用にオープンします。ファイルが存在すればその内容は消去されて新しいファイルになります。成功するとファイルハンドルを戻り値として返します。失敗したときはnilと、エラーメッセージの2つが得られます。filenameを指定しない時は、現在のファイルハンドルを返します。
(例)a.txt ファイルを新規作成して文字を書く。すでに存在すると、何もしない。 if io.output( "a.txt") then io.write( "result is 123" ) io.output() end

io.read( [format] )

現在の入力装置からデータを読み込みます。読み込んだデータを戻り値として返します。失敗した場合は、 nilになります。formatは、次のいずれかの文字列です。
	"*l",1行単位
	"*n",単語単位
	"*w", ファイルすべて
	"*n" 数値データ
指定のないときは行単位になります。また、数値を指定すると、指定したバイト数の読み込みをします。
(例)ファイルに書かれた数字データをすべて読んでテーブルに入れます。(ただし、1e10といった指数つきデータは読めません。)
data = {} one=io.input( "datas.txt" ) while(one) one= io.read( "*n") if(one) then table.insert(data,one) end end

io.write( value1, value2, ...)

現在の出力装置に与えられたデータvalue1, value2, ... を出力します。戻り値は成功すればtrue、失敗したときにnilとなります。

(例) io.write( "a = ", a )

オペレーティングシステムの機能呼び出し

os.remove( filename )

filenameで指定されたファイルを削除します。失敗したときは戻り値がnilになります。
(例)
	a, error = ( "c:\doc\arq.txt" )
	if not a then print( error )end

os.rename( name1, name2 )

name1のファイル名をname2に変更します。失敗した時の返り値はnilになります。
(例)
	a, error = oos.rename( "arq.txt", "arquivo.txt" )
	if not a thenprint( error )
	
	---endarq.txt を arquivo.txt に変更します。変更できなければメッセージを出力します。

os.tmpname( )

一時ファイルとして安全に使えるファイル名を返り値として返します。
(例)作業ファイルに書き込み準備する
filename = os.tmpname()
io.output( filename )

os.date( [format [, time] ] )


現在の日付と時刻を取得して文字列を戻り値として返します。書式を指定するformatは、unixのstrftime(2)で使われているもので、省略するとそのオペレーティングシステムで一般的な形式となります。timeとして数値が指定されていると、その数値の示す時刻になります。特別な機能として、formatに"*t"を与えて、strftimeのすべての項目をテーブルとして得ることもできます。
     %a        省略形の曜日
     %A        完全な曜日
     %b        省略形の月
     %B        月
     %c        一般的な日付と時刻
     %d        日付 01 〜 31
     %H        時 00 〜 23
     %I        時間 01 〜 12
     %j        今年の通算日数 001 〜 366
     %m        月 01 〜12
     %M        分 00 〜 59
     %P        午前午後 am/pm
     %S        秒 00 〜 60
     %U        今年の通算週数 日曜から 00 〜 53
     %w        今週の日曜からの日数  0 〜 6
     %W        今年の通算週数月曜から 00 〜 53
     %x        一般的な日付表記
     %X        一般的な時間表記
     %y        年の下2桁
     %Y        4桁の年
     %z        タイムゾーン
     %%        文字としての%
(例)print( os.date( "day %d month %B") )
(結果) day 14 month August

os.exit( [code] )

プログラムの実行を終了して数値codeをオペレーティングシステムにおけるプログラムの終了値とします。codeを指定しないときは1です。この関数は戻り値はありません。
(例)大域変数termina=programaが設定されていると、プログラムを終了させます。

os.getenv( varname )

オペレーティングシステムから与えられる環境変数から、文字列varnameで示されるデータを戻り値として返します。環境変数が存在しないときはnilになります。
(例)print( os.getenv( "REMOTE_HOST" ) )
環境変数 REMOTE_HOSTをプリントします。

os.execute( command )

オペレーティングシステムのシェル機能を使い、文字列 command をシェルの実行コマンドとして実行します。戻り値はコマンドの終了コードで、システムに依存します。ommandを省略すると、シェル機能が利用可能かどうかを返します。
(例)
os.execute("mkdir c:\data" )

最後に

Luaの特徴の一つに、産業界と大学の両面で利用されていることがあげられます。PUC-Rioで開発されたプログラムは、産業界では1998年までに数十のプロジェクトに利用され、学術的にも、多数の学位論文や学術論文で議論されました。2007年現在はさらに普及が進んでいます。
Luaは1994年2月にはじめてインターネットに公開され、ブラジル国内だけでなく海外にも広がりました。そして、様々な種類のアプリケーションプログラムに利用されるようになりました。単に使われされただけではなく、ユーザから様々なフィードバック情報がよせられています。  TeCGrafは、リオデジャネイロ大学とPETROBRA'S社の共同研究機関として設立された研究所で、視覚的なユーザーインターフェイスと、科学技術のためのアプリケーションソフトウェア開発とその維持を行っています。Luaはざまざまな設計のソフトウェア開発に利用することができました。そして、20人以上が常にLuaを仕事に使っており、ほかの人たちも最終的には使うようになりました。プログラムの合計は10万行以上になるでしょう。それらは学術雑誌の"Software: Practice & Experience"にも紹介しましたが、 TeCGrafのホームページにより多くの紹介があります。

ソフトウェア工学として

Luaの設計では、様々な先進的なメカニズムを導入しています。しかし、抽象的な概念をむやみに入れないのが特徴です。これによってLuaは、同じような機能のほかの言語と比べて相当シンプルで小型になっています。 その一例は、言語機能と、テーブルの機能をうまく分離しました。そして、これをオブジェクトとして使うためにフォールバックを導入しました。それから、ソフトウェアの部品を活用したボトムアップ型の開発スタイルを推進しています。Luaはつなぎ合わせる言語ともいえます。ソフトウェアシステムの多くの部分が関数ライブラリとして開発され、少数のスクリプトをLuaで記述することによって、アプリケーション全体を構築する手法といえるでしょう。

ソフトウェア開発の事例

現在までに数多くのソフトウェア開発に利用されてきました。この文書が最初に書かれた1994年時点の事例は次のようなものがあります。インターネットのニュースグループ等でも評価されてきましたが、それらは現在は別のサイトでも紹介されていますので、ここでは割愛します。

Sistema RPA@PUC (Network of Academic Profiles of PUC-Rio)

リオデジャネイロ・カトリカ大学の副学長のもとで開発された学術成果発表アーカイブのシステムに利用されています。発表は、"ジャーナル記事"、"ブック章"、"レビュー"、"翻訳"、"教材"などの種類があり、それらをLuaのテーブルで表現しています。webブラウザからcgiインターフェイスで更新したりレポートにするプログラムもLuaで書かれました。当時は約150人の教師や職員が日常的に利用しており、他大学での利用も計画されています(http://www.inf.puc-rio.br/~info-rpa/projeto/ )。また類似のシステムが計算機工学科のサイトでも使われています。( http://www.cos.ufrj.br/equipe/webmaster.html )

Medialab

Medialabはブラジルのインターネット企業で、シェルやMicrosoftのサイト構築にあたり、様々な動的なwebサイトの構築にLuaを使用しています。cgiによる検索エンジンもあり、フォルクスワーゲン、携帯電話会社、バーバラレストランガイドのサイトにも利用されたようです。
(http://www.volkswagen.com.br/indbusca.htm) and the system
(http://www.brazilweb.com/rio /)

Non-Linear Control Consultants Ltd

Dr.Dobbs誌に掲載されたLuaの記事を見て最初に問い合わせをいただいたのが、このイギリスの会社のMark Ian Barlow 氏でした。

この文章の著作権について

Copyright (c) 1994-1998 TeCGraf, PUC-Rio. Written by Waldemar Celes Filho, Roberto Ierusalimschy, Luiz Henrique de Figueiredo. All rights reserved.
Permission is hereby granted, without written agreement and without license or royalty fees, to use, copy, modify, and distribute this software and its documentation for any purpose, subject to the following conditions:

* The above copyright notice and this permission notice shall appear in all copies or substantial portions of this software.

* The name "Lua" cannot be used for any modified form of this software that does not originate from the authors. Nevertheless, the name "Lua" may and should be used to designate the language implemented and described in this package, even if embedded in any other system, as long as its syntax and semantics remain unchanged.

The authors specifically disclaim any warranties, including, but not limited to, the implied warranties of merchantability and fitness for a particular purpose. The software provided hereunder is on an "as is" basis, and the authors have no obligation to provide maintenance, support, updates, enhancements, or modifications. In no event shall TeCGraf, PUC-Rio, or the authors be liable to any party for direct, indirect, special, incidental, or consequential damages arising out of the use of this software and its authors be liable to any party for direct, indirect, special, incidental, or consequential damages arising out of the use of this software and its documentation.