| ルア | |
|---|---|
| パラダイム | マルチパラダイム:スクリプト、命令型(手続き型、プロトタイプベース、オブジェクト指向)、関数型、メタ、リフレクティブ |
| デザイン: | ロベルト・イエルサリムシ・ワルデマール・セレス・ルイス・エンリケ・デ・フィゲイレド |
| 初登場 | 1993 (1993年) |
| 安定版リリース | |
| タイピングの規律 | ダイナミック、力強い、アヒル |
| 実装言語 | ANSI C |
| OS | クロスプラットフォーム |
| ライセンス | マサチューセッツ工科大学 |
| ファイル名拡張子 | .lua |
| Webサイト | www.lua.org |
| 主要な実装 | |
| Lua、LuaJIT、LuaVela、 MoonSharp、 | |
| 方言 | |
| GSL シェル、Lua u | |
| 影響を受けた | |
| C++、CLU、Modula、Scheme、SNOBOL | |
| 影響を受けた | |
| GameMonkey、Io、JavaScript、Julia、Red、Ring、[ 2 ] 、 Ruby、Squirrel、C--、Luau、 | |
Lua (/ ˈ l uː ə / LOO -ə ;ポルトガル語:lua [ˈlu(w)ɐ](月の意味)は、主にアプリケーションへの組み込み向けに設計された軽量で高水準のマルチパラダイムプログラミング言語です。[ 3 ] Luaはクロスプラットフォームソフトウェアであり、コンパイルされたバイトコードのインタープリタはANSI Cで書かれています。[ 4 ]また、Luaにはアプリケーションに組み込むための比較的シンプルなCアプリケーションプログラミングインターフェイス(API)があります。[ 5 ]
Luaは1993年、当時高まるカスタマイズ需要に応えるため、ソフトウェアアプリケーションを拡張するための言語として誕生しました。Luaはほとんどの手続き型プログラミング言語の基本的な機能を備えていましたが、より複雑な機能やドメイン固有の機能は含まれていませんでした。その代わりに、言語を拡張するためのメカニズムを備えており、プログラマーがそのような機能を実装できるようにしていました。Luaは汎用的な組み込み拡張言語となることを目指していたため、設計者は開発における速度、移植性、拡張性、そして使いやすさの向上に重点を置きました。
Lua は、1993 年にブラジルのリオデジャネイロ・ポンティフィカル・カトリック大学のコンピュータ グラフィックス テクノロジー グループ ( Tecgraf )のメンバーであるRoberto Ierusalimschy 、Luiz Henrique de Figueiredo、Waldemar Celesによって作成されました。
1977年から1992年まで、ブラジルはコンピュータのハードウェアとソフトウェアに対して強力な貿易障壁(市場留保政策)を敷いていました。これは、ブラジルが自国でハードウェアとソフトウェアを生産できる、そして生産すべきだと信じていたためです。このような状況下では、Tecgrafの顧客は政治的にも財政的にも、海外からカスタマイズされたソフトウェアを購入する余裕がありませんでした。市場留保政策の下では、顧客はブラジル企業ではニーズを満たせないことを証明するために、複雑な官僚的な手続きを経なければなりませんでした。こうした理由から、Tecgrafは必要な基本ツールをゼロから実装することにしました。[ 6 ]
Luaの前身は、データ記述言語と設定言語であるシンプルオブジェクト言語(SOL)とデータエントリ言語(DEL)でした。[ 7 ]これらは、1992年から1993年にかけてTecgrafで独立して開発され、2つの異なるプロジェクト(どちらもペトロブラス社のエンジニアリングアプリケーション用のインタラクティブグラフィカルプログラム)に柔軟性を追加するものでした。SOLとDELにはフロー制御構造が欠如しており、ペトロブラスはこれらに完全なプログラミング機能を追加する必要性が高まっていると感じていました。
Luaの進化の中で、この言語の作者は次のように書いている: [ 6 ]
1993 年、唯一の真の競合相手は、アプリケーションに組み込むことを明確に目的として設計された Tcl でした。しかし、Tcl は構文がわかりにくく、データ記述のサポートが不十分で、Unix プラットフォームでしか実行できませんでした。LISP や Scheme は構文が使いにくいため、検討対象とはしませんでした。Pythonはまだ初期段階でした。当時 Tecgraf には自由で DIY の雰囲気が広がっていたため、独自のスクリプト言語を開発しようとするのはごく自然なことでした... この言語の潜在的なユーザーの多くはプロのプログラマーではなかったので、この言語では難解な構文やセマンティクスを避ける必要がありました。Tecgraf のクライアントは多種多様なコンピューター プラットフォームを使用していたため、新しい言語の実装は移植性が高くなければなりませんでした。最後に、他の Tecgraf 製品にもスクリプト言語を組み込む必要があると予想されたため、新しい言語は SOL の例に倣い、C API 付きのライブラリとして提供される必要がありました。
Lua 1.0は、オブジェクトコンストラクタが当時の軽量で柔軟なスタイルとは若干異なっており、SOLのデータ記述構文を取り入れた設計でした(Luaという名前は、ポルトガル語でSolが「太陽」、Luaが「月」を意味することに由来しています)。制御構造のLua構文は、主にModula(if、、while/ )から借用しましたが、CLU(関数呼び出しからの多重代入と多重戻り。参照パラメータや明示的なポインタのよりシンプルな代替手段)、C++(「必要な場所にのみローカル変数を宣言できるという優れたアイデア」 [ 6 ])、SNOBOL、AWK(連想配列)の影響も受けています。Dr . Dobb's Journalに掲載された記事の中で、Luaの開発者は、LISPとSchemeの単一の普遍的なデータ構造メカニズム(リスト)が、Luaの主要データ構造としてテーブルを開発するという決定に大きな影響を与えたと述べています。[ 8 ]repeatuntil
Luaのセマンティクスは、時間の経過とともにSchemeの影響をますます受けてきており、[ 6 ]特に匿名関数と完全なレキシカルスコープの導入によって顕著になっています。新しいLuaのバージョンでは、いくつかの機能が追加されました。
Luaのバージョン5.0より前のバージョンは、 BSDライセンスに類似したライセンスの下でリリースされていました。バージョン5.0以降、LuaはMITライセンスの下でライセンスされています。どちらも寛容なフリーソフトウェアライセンスであり、内容はほぼ同じです。
Luaは一般的に「マルチパラダイム」言語と呼ばれ、様々な問題の種類に合わせて拡張可能な、少数の汎用機能を提供します。Luaは継承を明示的にサポートしていませんが、メタテーブルを用いて実装できます。同様に、Luaでは、プログラマーが単一のテーブル実装を使用して、名前空間、クラス、その他の関連機能を実装できます。ファーストクラス関数により、関数型プログラミングの多くの手法を適用でき、完全なレキシカルスコープにより、きめ細かな情報隠蔽によって最小権限の原則を適用できます。
一般的に、Luaは、特定のプログラミングパラダイムに特化した機能セットを提供するのではなく、必要に応じて拡張可能なシンプルで柔軟なメタ機能を提供することを目指しています。その結果、ベース言語は軽量化され、完全なリファレンスインタプリタはコンパイル後わずか約247KB [4] で 、幅広いアプリケーションに容易に適応できます。
拡張言語またはスクリプト言語としての使用を目的とした動的型付け言語であるLuaは、様々なホストプラットフォームに適合するほどコンパクトです。ブール値、数値(デフォルトでは倍精度浮動小数点数と64ビット整数)、文字列といった、ごく少数のアトミックデータ構造のみをサポートしています。配列、セット、リスト、レコードといった一般的なデータ構造は、Luaの単一のネイティブデータ構造であるテーブルで表現できます。テーブルは、本質的には異種連想配列です。
Lua は、ファーストクラス関数、ガベージコレクション、クロージャ、適切な末尾呼び出し、強制変換 (実行時に文字列と数値を自動的に変換する)、コルーチン(協調型マルチタスク)、動的モジュール読み込みなどの高度な機能の小さなセットを実装しています。
古典的な「Hello, World!」プログラムは、括弧の有無にかかわらず次のように記述できます。[ 9 ] [ a ]
印刷( "Hello, World!" )「Hello, World!」と印刷します。値のない変数の宣言。
ローカル変数値が 10 である変数の宣言。
地元の学生= 10Lua のコメントは、 Ada、Eiffel、Haskell、SQL、VHDLと同様に、二重ハイフンで始まり、行末まで続きます。複数行の文字列とコメントは、二重角括弧で囲まれます。
-- 単一行コメント--[[複数行コメント--]]この例では階乗関数が実装されてい ます。
関数階乗( n )ローカルx = 1 i = 2 , n の場合x = x * iを実行end return x endLua には、オプションと実行制御構造 を持つ1 種類の条件テストがあります。if then endelseelseif then
汎用if then endステートメントには、次の 3 つのキーワードすべてが必要です。
if条件then --文本体終了if声明 の例
x ~= 10の場合、print ( x )を出力します。条件が次のように評価された場合に実行を制御するために、キーワードelseに付随するステートメント ブロックを追加することができます。 iffalse
if条件then --文本体else --文本体endif else声明 の例
x == 10の場合print ( 10 )、そうでない場合はprint ( x )、終了次のキーワードを使用して、複数の条件に応じて実行を制御することもできますelseif then。
if条件then --文本体elseif条件then --文本体else --オプション--オプション デフォルト文本体endif elseif else声明 の例
x == yの場合、print ( "x = y" ) elseif x == zの場合、print ( "x = z" ) else -- オプションprint ( "x は他のどの変数とも等しくありません" ) endwhileLua には、ループ、repeatループ (do whileループに似ています)、数値forループ、および汎用ループの 4 種類の条件付きループがありますfor。
--条件 = 真while条件do --ステートメント終了条件が満たされるまでステートメントを繰り返すfor i = first , last , delta do --delta は負の値でも構いません。for ループでカウントダウンまたはカウントアップできます--statements --example: print(i) endこの汎用ループは、標準の反復関数を使用して、次の結果が返されるまでforテーブルを反復処理します。 _Gpairsnil
キーと値のペア( _G )に対して、 print (キー、値)を実行します。ループはネスト(別のループ内に入れる) することもできます。
ローカルグリッド= { { 11 , 12 , 13 }, { 21 , 22 , 23 }, { 31 , 32 , 33 } }for y , row in pairs ( grid ) do for x , value in pairs ( row ) do print ( x , y , value ) end endLua が関数をファーストクラスの値として扱う方法は次の例に示されています。この例では、print 関数の動作が変更されています。
do local oldprint = print -- 現在のprint関数をoldprint関数として保存するprint ( s ) --[[ print関数を再定義する。通常のprint関数は oldprintを通して引き続き使用できる。新しいprint関数は引数を1つだけ持つ。]] oldprint ( s == "foo" and "bar" or s ) end end今後の の呼び出しは新しい関数を経由してルーティングされるようになり、Lua の語彙スコープprintにより、古い print 関数は新しい変更された print からのみアクセス可能になります。
以下に示すように、 Lua はクロージャもサポートしています。
function addto ( x ) -- 引数に x を加算する新しい関数を返すreturn function ( y ) --[[ 現在の スコープ外にあり、この匿名関数よりも寿命が短い変数 x を参照すると 、Lua はクロージャを作成します。]] return x + y end end fourplus = addto ( 4 ) print ( fourplus ( 3 )) -- 7 を出力します--これは、次のように関数を呼び出すことでも実現できます: print ( addto ( 4 )( 3 )) --[[ これは、 'addto(4)' から返された関数を引数 '3' で直接呼び出しているためです。 これにより、反復的に呼び出される場合のデータコストが削減され、パフォーマンスも向上します。]]変数が呼び出されるxたびに新しいクロージャが作成されるaddtoため、返される新しい匿名関数は常に自身のxパラメータにアクセスします。クロージャは、他のオブジェクトと同様に、Luaのガベージコレクタによって管理されます。
テーブルはLuaにおいて最も重要なデータ構造(そして設計上、唯一の組み込み複合データ型)であり、ユーザーが作成するすべての型の基盤となります。テーブルは、自動数値キーと特殊な構文が追加された連想配列です。
テーブルはキーとデータのペアのセットであり、データはキーによって参照されます。つまり、ハッシュされた異種の連想配列です。
テーブルは{}コンストラクター構文を使用して作成されます。
a_table = {} -- 新しい空のテーブルを作成しますテーブルは常に参照によって渡されます (共有による呼び出しを参照)。
キー (インデックス) には、関数を含め、 NaN をnil除く任意の値を指定できます。
a_table = { x = 10 } -- 1 つのエントリが "x" を数値 10 にマッピングする新しいテーブルを作成します。print ( a_table [ "x" ]) -- 文字列キーに関連付けられた値 (この場合は 10) を出力します。b_table = a_table b_table [ "x" ] = 20 -- テーブルの値は 20 に変更されました。print ( b_table [ "x" ]) -- 20 を出力します。print ( a_table [ "x" ]) -- a_table と b_table はどちらも同じテーブルを参照しているため、20 も出力されます。テーブルは、文字列をキーとして用いることで、構造体(またはレコード)として用いられることが多い。このような用途は非常に一般的であるため、Luaにはそのようなフィールドにアクセスするための特別な構文が用意されている。[ 11 ]
point = { x = 10 , y = 20 } -- 新しいテーブルを作成します。print ( point [ "x" ]) -- 10 を出力します。 print ( point . x ) -- 上の行と全く同じ意味です。読みやすいドット表記は単なる糖衣構文です。関連する関数を格納するテーブルを使用することで、名前空間として機能することができます。
ポイント= {}ポイント.new = function ( x , y ) return { x = x , y = y } -- return {["x"] = x, ["y"] = y } endPoint .set_x = function ( point , x ) point .x = x -- point["x"] = x ;終了テーブルには自動的に数値キーが割り当てられ、配列データ型として使用できます。最初の自動インデックスは、他の多くのプログラミング言語のように0ではなく1です(ただし、明示的に0を指定することも可能です)。
数値キーは1文字列キーとは異なります"1"。
array = { "a" , "b" , "c" , "d" } -- インデックスは自動的に割り当てられます。print ( array [ 2 ]) -- "b" を出力します。Lua の自動インデックスは 1 から始まります。print ( # array ) -- 4 を出力します。# はテーブルと文字列の長さを表す演算子です。array [ 0 ] = "z" -- 0 は有効なインデックスです。print ( # array ) -- Lua の配列は 1 から始まるため、やはり 4 を出力します。テーブルの長さは、が でなくであるようなt任意の整数インデックスとして定義されます。さらに、が である場合、はゼロになることがあります。1 から指定された までの nil 以外の値を持つ通常の配列の場合、その長さは最後の値のインデックスとまったく同じになります。配列に「穴」(つまり、他の nil 以外の値の間に nil 値がある)がある場合、 は値の直前のインデックスのいずれかになります(つまり、そのような nil 値を配列の末尾と見なす場合があります)。[ 12 ]nt[n]nilt[n+1]nilt[1]nilnnn#tnil
ExampleTable = { { 1 , 2 , 3 , 4 }, { 5 , 6 , 7 , 8 } } print ( ExampleTable [ 1 ][ 3 ]) -- "3" を出力しますprint ( ExampleTable [ 2 ][ 4 ]) -- "8" を出力しますテーブルはオブジェクトの配列にすることができます。
function Point ( x , y ) -- "Point"オブジェクトコンストラクタreturn { x = x , y = y } -- 新しいオブジェクト(テーブル)を作成して返しますend array = { Point ( 10 , 20 ), Point ( 30 , 40 ), Point ( 50 , 60 ) } -- 点の配列を作成します-- array = { { x = 10, y = 20 }, { x = 30, y = 40 }, { x = 50, y = 60 } }; print ( array [ 2 ]. y ) -- 40を出力しますハッシュマップを使用して配列をエミュレートすると、実際の配列を使用するよりも遅くなりますが、Luaテーブルはこの問題を回避するために配列として使用できるように最適化されています。[ 13 ]
拡張可能なセマンティクスはLuaの重要な機能であり、メタテーブルによってテーブルを強力にカスタマイズできます。次の例は「無限」テーブルの例です。任意の に対してn、は動的計画法とメモ化を用いて- 番目のフィボナッチ数をfibs[n]返します。 n
fibs = { 1 , 1 } -- fibs[1]とfibs[2]の初期値。setmetatable ( fibs , { __index = function ( values , n ) -- [[__indexはLuaで定義済みの関数で、 キー"n"が存在しない場合に呼び出されます。]] values [ n ] = values [ n - 1 ] + values [ n - 2 ] -- fibs[n]を計算してメモ化します。return values [ n ] end } )Luaにはクラスの概念が組み込まれていませんが、関数とテーブルを用いることでオブジェクト指向プログラミングをエミュレートできます。オブジェクトは、メソッドとフィールドをテーブルに格納することで形成されます。継承(単一継承と多重継承の両方)はメタテーブルを用いて実装でき、存在しないメソッドとフィールドを親オブジェクトに委譲することができます。
これらの手法には「クラス」という概念はなく、SelfやJavaScriptと同様にプロトタイプが使用されます。新しいオブジェクトは、ファクトリーメソッド(新しいオブジェクトをゼロから構築するメソッド)または既存のオブジェクトのクローンによって作成されます。
基本的なベクターオブジェクトの作成:
ローカルVector = {}ローカルVectorMeta = { __index = Vector }function Vector.new ( x , y , z ) -- コンストラクタreturn setmetatable ( { x = x , y = y , z = z } , VectorMeta ) endfunction Vector.magnitude ( self ) --別の方法return math.sqrt ( self.x ^ 2 + self.y ^ 2 + self.z ^ 2 ) endlocal vec = Vector . new ( 0 , 1 , 0 ) -- ベクトルを作成するprint ( vec . magnification ( vec )) -- メソッドを呼び出す (出力: 1) print ( vec . x ) -- メンバー変数にアクセスする (出力: 0)ここで、 は、 Lua に、要素がテーブルに存在しない場合にテーブルsetmetatable内を検索するように指示します。は と同等であり、まずテーブル内で要素を検索します。テーブルには要素がありませんが、そのメタテーブルは、要素がテーブルに見つからない場合、テーブルに要素の検索を委譲します。 Vectorvecvec.magnitudevec["magnitude"]vecmagnitudevecmagnitudeVectormagnitudevec
Luaはオブジェクト指向を容易にするための糖衣構文を提供しています。プロトタイプテーブル内でメンバー関数を宣言するには、 を使用します。これは と同等です。クラスメソッドの呼び出しにもコロンを使用します。は と同等です。 functiontable:func(args)functiontable.func(self,args)object:func(args)object.func(object,args)
:それを念頭に置いて、構文糖衣 を含む対応するクラスを次に示します。
ローカルベクトル= {}ベクトル. __index =ベクトルfunction Vector : new ( x , y , z ) -- コンストラクタ-- 関数定義ではコロンが使用されているため、-- 最初の引数は "self" で、これは"Vector" を参照します。 return setmetatable ({ x = x , y = y , z = z }, self ) endfunction Vector : magnitude () -- 別の方法-- self を使用して暗黙のオブジェクトを参照するreturn math.sqrt ( self . x ^ 2 + self . y ^ 2 + self . z ^ 2 ) endlocal vec = Vector : new ( 0 , 1 , 0 ) -- ベクトルを作成するprint ( vec : magnitude ()) -- メソッドを呼び出す (出力: 1) print ( vec . x ) -- メンバー変数にアクセスする (出力: 0)メタテーブルを使うとLuaのクラス継承の動作を模倣することができます。[ 14 ]この例では、派生クラスでベクトルの値を定数で乗算できるようにします。
ローカルベクトル= {}ベクトル. __index =ベクトルfunction Vector : new ( x , y , z ) -- コンストラクタ-- ここで、self は呼び出されるクラスの "new" メソッドを指します。派生クラスでは、self は派生クラスになります。Vector クラスでは、selfは Vector になります。 return setmetatable ({ x = x , y = y , z = z }, self ) endfunction Vector : magnitude () -- 別の方法-- self を使用して暗黙のオブジェクトを参照するreturn math.sqrt ( self . x ^ 2 + self . y ^ 2 + self . z ^ 2 ) end-- 疑似クラス継承の例local VectorMult = {} VectorMult . __index = VectorMult setmetatable ( VectorMult , Vector ) -- VectorMult を Vector の子にする関数VectorMult : multiply ( value ) self.x = self.x * value self.y = self.y * value self.z = self.z * value return self endlocal vec = VectorMult : new ( 0 , 1 , 0 ) -- ベクトルを作成します。print ( vec : magnitude ()) -- メソッドを呼び出します (出力: 1) print ( vec . y ) -- メンバー変数にアクセスします (出力: 1) vec : multiply ( 2 ) -- ベクトルのすべての要素を 2 で乗算します。print ( vec . y ) -- メンバーに再度アクセスします (出力: 2)多重継承を実装することも可能です。__index関数またはテーブルのいずれかになります。[ 15 ]演算子のオーバーロードも可能です。Luaのメタテーブルには__add、、などの要素を含めることができます__sub。[ 16 ]
Luaプログラムはテキスト形式のLuaファイルから直接解釈されるのではなく、バイトコードにコンパイルされ、Lua仮想マシン(VM)上で実行されます。このコンパイルプロセスは通常、ユーザーには見えず、実行時に実行されます。特にJIT( Just-In-Time Compilation)コンパイラを使用する場合は顕著ですが、オフラインで実行することで読み込みパフォーマンスを向上させたり、コンパイラを介さずにホスト環境のメモリ使用量を削減したりすることも可能です。Luaバイトコードは、dump文字列ライブラリの関数とload/loadstring/loadfile関数を使用して、Lua内部から生成・実行することもできます。Luaバージョン5.3.4は、約24,000行のCコードで実装されています。[ 3 ] [ 4 ]
ほとんどのCPUと同様に、またスタックベースの仮想マシンとは異なり、Lua VMはレジスタベースであるため、ほとんどのハードウェア設計に近いものとなっています。レジスタアーキテクチャは、値の過剰なコピーを回避し、関数あたりの命令の総数を削減します。Lua 5の仮想マシンは、広く普及した最初のレジスタベースの純粋なVMの1つです。[ 17 ] ParrotとAndroidのDalvikは、他によく知られているレジスタベースのVMです。PCSchemeのVMもレジスタベースでした。[ 18 ]
この例は、上で定義した階乗関数のバイトコードリストです(5.1コンパイラによって表示されますluac)。[ 19 ]
関数 <factorial.lua:1,7> (9命令、0x8063c60の36バイト) 1 個のパラメータ、6 個のスロット、0 個のアップ値、6 個のローカル変数、2 個の定数、0 個の関数 1 [2] ロード 1 -1 ; 1 2 [3] ロードK 2 -2 ; 2 3 [3] 移動 3 0 4 [3] ロードク 4 -1 ; 1 5 [3] FORPREP 2 1 ; ~ 7 6 [4] マルチ 1 1 5 7 [3] FORLOOP 2 -2 ; 6まで 8 [6] 戻る 1 2 9 [7] リターン 0 1
Luaは他のアプリケーションに組み込むことを目的としており、そのためのC APIを提供しています。APIは、LuaコアとLua補助ライブラリの2つの部分に分かれています。 [ 20 ] Lua APIの設計により、 Python APIとは異なり、Cコードで手動で参照カウント(管理)する必要がありません。APIは、言語と同様に最小限に抑えられています。高度な機能は補助ライブラリによって提供され、主に複雑なテーブル操作を支援する プリプロセッサマクロで構成されています。
Lua C API はスタックベースです。Lua は、ほとんどの単純な C データ型 (整数、浮動小数点数など) をスタックにプッシュおよびポップする関数と、スタックを介してテーブルを操作する関数を提供します。Lua のスタックは従来のスタックとは多少異なり、たとえばスタックに直接インデックスを付けることができます。負のインデックスはスタックの先頭からのオフセットを示します。たとえば、-1 は先頭 (最後にプッシュされた値) であり、正のインデックスは末尾 (最も古い値) からのオフセットを示します。C関数と Lua 関数の間でのデータの整列化もスタックを使用して行われます。Lua 関数を呼び出すには、引数をスタックにプッシュし、それをlua_call使用して実際の関数を呼び出します。Lua から直接呼び出される C 関数を作成する場合、引数はスタックから読み取られます。
以下は C から Lua 関数を呼び出す例です。
#include <stdio.h> #include <lua.h> // Luaメインライブラリ (lua_*) #include <lauxlib.h> // Lua補助ライブラリ (luaL_*)int main ( void ) { // Lua ステートを作成しますlua_State * L = luaL_newstate ();// 文字列を読み込んで実行するif ( luaL_dostring ( L , "function foo (x,y) return x+y end" )) { lua_close ( L ); return -1 ; }// グローバル "foo" (上記で定義した関数) の値をスタックにプッシュし、その後に整数 5 と 3 をプッシュします。 lua_getglobal ( L , "foo" ); lua_pushinteger ( L , 5 ); lua_pushinteger ( L , 3 ); lua_call ( L , 2 , 1 ); // 2 つの引数と 1 つの戻り値を持つ関数を呼び出します。printf ( "Result: %d \n " , lua_tointeger ( L , -1 )); // スタックの先頭にある項目の整数値を出力します。lua_pop ( L , 1 ); // スタックを元の状態に戻します。lua_close ( L ); // Lua の状態を閉じます。return 0 ; }この例を実行すると次のようになります。
$ cc -o example example.c -llua $ ./example 結果: 8C APIは、Luaスタック内の様々な「疑似インデックス」に配置された特別なテーブルも提供しています。Lua LUA_GLOBALSINDEX5.2 [ 21 ]より前のバージョンでは、Lua内部のグローバルテーブルが_Gメインの名前空間として存在していました。また、Cプログラムが後で取得するためにLuaの値を保存できるレジストリも存在しますLUA_REGISTRYINDEX。
標準ライブラリ (コア) モジュールの他に、Lua API を使用して拡張機能を記述することも可能です。拡張モジュールは共有オブジェクトであり、Lua スクリプトにネイティブ機能を提供することでインタープリタの機能を拡張するために使用できます。Lua スクリプトは、Lua 自身で記述されたモジュールと同様に、 [ 20 ] を使用して拡張モジュールをロードすることもrequire、[ 22 ]を使用して拡張モジュールをロードすることもできますpackage.loadlib。Cライブラリが 経由でロードされると、Luaは 関数を探して呼び出します。この関数は、Lua から呼び出し可能な任意の C 関数として動作し、通常はメソッドが入ったテーブルを返します。rocks と呼ばれるモジュールのセットは増え続けており、CPAN、RubyGems、Python eggsの精神にのっとり、 LuaRocksというパッケージ管理システムを通じて利用できます。[ 23 ]他のスクリプト言語を含む、ほとんどの一般的なプログラミング言語用に、事前に記述された Luaバインディングが存在します。 require('foo')luaopen_foo
ビデオゲーム開発において、Luaはスクリプト言語として広く使用されている。これは主に、組み込みの容易さ、実行の高速さ、学習曲線の短さなどが理由である。[ 25 ] Luaを使用している有名なゲームには、Roblox、[ 26 ] Garry's Mod、World of Warcraft、Payday 2、Project Zomboid、Phantasy Star Online 2、Dota 2、Crysis、[ 27 ]などがある。Luaプログラミングやスクリプトをネイティブでサポートしていないゲームでは、ComputerCraftがMinecraftに対して行っているように、modによってこの機能が追加されている。同様に、DiscordiaなどのLua APIライブラリは、Luaをネイティブでサポートしていないプラットフォームで使用されている。[ 28 ] Luaはオープンソースの2次元ゲームエンジンLÖVEで使用されている。[ 29 ]また、LuaはAdobe Lightroom、Moho、iClone、Aerospikeなどのビデオゲーム以外のソフトウェアや、FreeBSDとNetBSDの一部のシステムソフトウェアでも使用されており、Scribunto拡張機能を使用してMediaWikiのテンプレートスクリプト言語としても使用されています。[ 30 ]
2003年にGameDev.netが実施した世論調査では、Luaがゲームプログラミングで最も人気のあるスクリプト言語であることが示されました。[ 31 ] 2012年1月12日、Luaは雑誌Game Developerのプログラミングツール部門でFront Line Award 2011を受賞したことが発表されました。[ 32 ]
ゲーム以外の多くのアプリケーションでも、拡張性のために Lua が使用されています。たとえば、 TeX型設定言語の実装であるLuaTeX 、キー値データベースのRedis、ワイドカラムストアのScyllaDB 、テキストエディタのNeovim、Web サーバのNginx、ネットワーク パケット アナライザのWireshark 、 Discord API ライブラリのDiscordia 、ビジュアル オーディオ プログラミング言語のPure Data (pdlua 拡張機能経由) などです。
doend{}さらに、Luaユーザーコミュニティは、リファレンスC実装の上にいくつかの強力なパッチを提供しています。 [ 48 ]
{{cite web}}:欠落または空|title=(ヘルプ){{cite book}}:|work=無視されました (ヘルプ){{cite web}}: CS1 maint: bot: 元のURLステータス不明(リンク)これらすべてが、私たちがLua 5.1をベースに、Luauと呼ぶ新しい派生言語へと作り直すきっかけとなりました。私たちは、言語のパフォーマンスと機能を向上させ、リンティングと漸進的型システムを用いた型チェックを組み合わせることで、堅牢なコードを容易に記述できるようにすることに重点を置いています。