Lua チュートリアル
Luaを使い始める
サーチ…
備考
Luaは最小限で軽量で組み込み可能なスクリプト言語です。ブラジルのリオデジャネイロ教皇カトリック大学PUC-Rioの チームによって設計、実施、維持されています。 メーリングリストは開かれています。
Luaの一般的な使用例には、ビデオゲームのスクリプティング、プラグインと設定によるアプリケーションの拡張、高水準のビジネスロジックのラッピング、またはテレビ、車などのデバイスへの埋め込みなどがあります。
高性能タスクのために、 LuaJITと呼ばれるジャストインタイムコンパイラを使用した独立した実装があります。
バージョン
バージョン | ノート | 発売日 |
---|---|---|
1.0 | 初期の非公開リリース。 | 1993-07-28 |
1.1 | 最初の一般公開。それを記述する会議紙 。 | 1994年7月8日 |
2.1 | Lua 2.1以降、Luaは商用用途を含むあらゆる目的で自由に利用できるようになりました。それを記述するジャーナル紙 。 | 1995-02-07 |
2.2 | 長い文字列、デバッグインタフェース、より良いスタックトレースバック | 1995-11-28 |
2.4 | 外部luac コンパイラ | 1996-05-14 |
2.5 | パターンマッチングとvararg関数 | 1996年11月19日 |
3.0 | Luaライブラリの作成を支援するライブラリauxlibを導入 | 1997-07-01 |
3.1 | 匿名関数と関数は "upvalues"で終了します。 | 1998年7月11日 |
3.2 | ライブラリと新しいテーブル関数のデバッグ | 1999年7月8日 |
3.2.2 | 2000-02-22 | |
4.0 | 複数の状態、 "for"文、API改訂 | 2000-11-06 |
4.0.1 | 2002-07-04 | |
5.0 | コルーチン、メタテーブル、フルレキシカルスコープ、テールコール、ブール値はMITライセンスに移行します。 | 2003-04-11 |
5.0.3 | 2006-06-26 | |
5.1 | モジュールシステム改造、インクリメンタルガベージコレクタ、すべてのタイプのメタテーブル、luaconf.h改訂、完全なリエントラントパーサ、可変引数。 | 2006-02-21 |
5.1.5 | 2012-02-17 | |
5.2 | 緊急ガベージコレクタ、goto、テーブルのファイナライザ | 2011-12-16 |
5.2.4 | 2015-03-07 | |
5.3 | 基本的なUTF-8サポート、bitwise ops、32 / 64bit整数 | 2015-01-12 |
5.3.4 | 最新バージョン。 | 2017-01-12 |
インストール
バイナリ
Luaのバイナリは、ほとんどのGNU / Linuxディストリビューションでパッケージとして提供されています。
たとえば、Debian、Ubuntu、およびその派生物では、これを実行することで取得できます:
sudo apt-get install lua50
sudo apt-get install lua51
sudo apt-get install lua52
SourceForge 、MacOS、およびSourceForgeでホストされている他のオペレーティングシステム用に用意された半正式なビルドがあります 。
Appleのユーザーは、 Homebrewを使って簡単にLuaをインストールすることもできます:
brew install lua
(現在のところ、Homebrewは5.2.4、5.3はHomebrew / versionsを参照)。
ソース
ソースは公式ページから入手できます 。ソースの取得と構築自体は簡単ではありません。 Linuxシステムでは、次のように十分なはずです。
$ wget http://lua.org/ftp/lua-5.3.3.tar.gz
$ echo "a0341bc3d1415b814cc738b2ec01ae56045d64ef ./lua-5.3.3.tar.gz" | sha1sum -c -
$ tar -xvf ./lua-5.3.3.tar.gz
$ make -C ./lua-5.3.3/ linux
上記の例では、公式サイトからソースtarball
をダウンロードし、チェックサムを検証し、 make
を抽出して実行しmake
ます。 ( 公式ページでチェックサムをダブルチェックしてください 。)
注:ビルドターゲットを指定する必要があります。この例では、 linux
を指定しました。その他の使用可能なビルドターゲットには、 solaris
、 aix
、 bsd
、 freebsd
、 macosx
、 mingw
などがあります。詳細は、ソースに含まれているdoc/readme.html
参照してください。 ( 最新のREADMEもオンラインで入手できます 。)
モジュール
標準ライブラリはプリミティブに限定されています。
-
coroutine
- コルーチン管理機能 -
debug
- デバッグフックとツール -
io
- 基本IOプリミティブ -
package
- モジュール管理機能 -
string
列とLua固有のパターンマッチング機能 -
table
- 本質的だが複雑なLuaタイプを扱うためのプリミティブ - テーブル -
os
- 基本的なOS操作 -
utf8
- 基本的なUTF-8プリミティブ(Lua 5.3以降)
これらのライブラリはすべて、特定のビルドのために無効にすることも、実行時にロードすることもできます。
モジュールを配布するための第三者のLuaライブラリとインフラストラクチャはまばらですが、改善しています。以下のようなプロジェクトLuaRocks 、 Luaのツールボックス 、およびLuaDistは 、状況を改善しています。多くの情報と多くの提案が古いLua Wikiで見つかることがありますが、この情報のいくつかはかなり古いものであることに注意してください。
コメント
Luaの1行のコメントは--
で始まり、行末まで続きます:
-- this is single line comment
-- need another line
-- huh?
ブロックコメントは--[[
とで終わる]]
始まり]]
:
--[[
This is block comment.
So, it can go on...
and on...
and on....
]]
ブロックコメントは、長い文字列と同じスタイルの区切り文字を使用します。コメントを区切るために、任意の数の等号を括弧の間に追加することができます。
--[=[
This is also a block comment
We can include "]]" inside this comment
--]=]
--[==[
This is also a block comment
We can include "]=]" inside this comment
--]==]
コードの塊をコメントするためのきちんとしたトリックは、それを--[[
と--]]
囲むこと--]]
:
--[[
print'Lua is lovely'
--]]
チャンクを再度アクティブにするには、単にコメントの開始シーケンスに-
を追加します。
---[[
print'Lua is lovely'
--]]
このように、シーケンス--
最初の行には、ちょうど最後の行のように、単一行コメントを開始し、 print
文はコメントアウトされていません。
これをさらに進めると、最初のブロックがコメントアウトされていても2番目のブロックがコメントアウトされていなければ、2つのコードブロックが設定されます。
---[[
print 'Lua is love'
--[=[]]
print 'Lua is life'
--]=]
最初のチャンクを無効にしながら、アクティブ第二のチャンクに、先頭を削除-
最初の行に:
--[[
print 'Lua is love'
--[=[]]
print 'Lua is life'
--]=]
Luaプログラムの実行
通常、Luaには2つのバイナリが付属しています。
-
lua
- スタンドアロンインタプリタとインタラクティブシェル -
luac
- バイトコードコンパイラ
次のようなサンプルプログラム( bottles_of_mate.lua
)があるとしましょう:
local string = require "string"
function bottle_take(bottles_available)
local count_str = "%d bottles of mate on the wall."
local take_str = "Take one down, pass it around, " .. count_str
local end_str = "Oh noes, " .. count_str
local buy_str = "Get some from the store, " .. count_str
local bottles_left = 0
if bottles_available > 0 then
print(string.format(count_str, bottles_available))
bottles_left = bottles_available - 1
print(string.format(take_str, bottles_left))
else
print(string.format(end_str, bottles_available))
bottles_left = 99
print(string.format(buy_str, bottles_left))
end
return bottles_left
end
local bottle_count = 99
while true do
bottle_count = bottle_take(bottle_count)
end
あなたのシェルで次のように実行することで、プログラム自体を実行することができます:
$ lua bottles_of_mate.lua
出力は次のようになり、無限ループで実行されます。
Get some from the store, 99 bottles of mate on the wall.
99 bottles of mate on the wall.
Take one down, pass it around, 98 bottles of mate on the wall.
98 bottles of mate on the wall.
Take one down, pass it around, 97 bottles of mate on the wall.
97 bottles of mate on the wall.
...
...
3 bottles of mate on the wall.
Take one down, pass it around, 2 bottles of mate on the wall.
2 bottles of mate on the wall.
Take one down, pass it around, 1 bottles of mate on the wall.
1 bottles of mate on the wall.
Take one down, pass it around, 0 bottles of mate on the wall.
Oh noes, 0 bottles of mate on the wall.
Get some from the store, 99 bottles of mate on the wall.
99 bottles of mate on the wall.
Take one down, pass it around, 98 bottles of mate on the wall.
...
あなたのシェルで以下を実行することで、プログラムをLuaのバイトコードにコンパイルすることができます:
$ luac bottles_of_mate.lua -o bottles_of_mate.luac
また、以下のコードを実行することによって、バイトコードのリストを利用できます。
$ luac -l bottles_of_mate.lua
main <./bottles.lua:0,0> (13 instructions, 52 bytes at 0x101d530)
0+ params, 4 slots, 0 upvalues, 2 locals, 4 constants, 1 function
1 [1] GETGLOBAL 0 -1 ; require
2 [1] LOADK 1 -2 ; "string"
3 [1] CALL 0 2 2
4 [22] CLOSURE 1 0 ; 0x101d710
5 [22] MOVE 0 0
6 [3] SETGLOBAL 1 -3 ; bottle_take
7 [24] LOADK 1 -4 ; 99
8 [27] GETGLOBAL 2 -3 ; bottle_take
9 [27] MOVE 3 1
10 [27] CALL 2 2 2
11 [27] MOVE 1 2
12 [27] JMP -5 ; to 8
13 [28] RETURN 0 1
function <./bottles.lua:3,22> (46 instructions, 184 bytes at 0x101d710)
1 param, 10 slots, 1 upvalue, 6 locals, 9 constants, 0 functions
1 [5] LOADK 1 -1 ; "%d bottles of mate on the wall."
2 [6] LOADK 2 -2 ; "Take one down, pass it around, "
3 [6] MOVE 3 1
4 [6] CONCAT 2 2 3
5 [7] LOADK 3 -3 ; "Oh noes, "
6 [7] MOVE 4 1
7 [7] CONCAT 3 3 4
8 [8] LOADK 4 -4 ; "Get some from the store, "
9 [8] MOVE 5 1
10 [8] CONCAT 4 4 5
11 [9] LOADK 5 -5 ; 0
12 [11] EQ 1 0 -5 ; - 0
13 [11] JMP 16 ; to 30
14 [12] GETGLOBAL 6 -6 ; print
15 [12] GETUPVAL 7 0 ; string
16 [12] GETTABLE 7 7 -7 ; "format"
17 [12] MOVE 8 1
18 [12] MOVE 9 0
19 [12] CALL 7 3 0
20 [12] CALL 6 0 1
21 [13] SUB 5 0 -8 ; - 1
22 [14] GETGLOBAL 6 -6 ; print
23 [14] GETUPVAL 7 0 ; string
24 [14] GETTABLE 7 7 -7 ; "format"
25 [14] MOVE 8 2
26 [14] MOVE 9 5
27 [14] CALL 7 3 0
28 [14] CALL 6 0 1
29 [14] JMP 15 ; to 45
30 [16] GETGLOBAL 6 -6 ; print
31 [16] GETUPVAL 7 0 ; string
32 [16] GETTABLE 7 7 -7 ; "format"
33 [16] MOVE 8 3
34 [16] MOVE 9 0
35 [16] CALL 7 3 0
36 [16] CALL 6 0 1
37 [17] LOADK 5 -9 ; 99
38 [18] GETGLOBAL 6 -6 ; print
39 [18] GETUPVAL 7 0 ; string
40 [18] GETTABLE 7 7 -7 ; "format"
41 [18] MOVE 8 4
42 [18] MOVE 9 5
43 [18] CALL 7 3 0
44 [18] CALL 6 0 1
45 [21] RETURN 5 2
46 [22] RETURN 0 1
入門
変数
var = 50 -- a global variable
print(var) --> 50
do
local var = 100 -- a local variable
print(var) --> 100
end
print(var) --> 50
-- The global var (50) still exists
-- The local var (100) has gone out of scope and can't be accessed any longer.
タイプ
num = 20 -- a number
num = 20.001 -- still a number
str = "zaldrizes buzdari iksos daor" -- a string
tab = {1, 2, 3} -- a table (these have their own category)
bool = true -- a boolean value
bool = false -- the only other boolean value
print(type(num)) --> 'number'
print(type(str)) --> 'string'
print(type(bool)) --> 'boolean'
type(type(num)) --> 'string'
-- Functions are a type too, and first-class values in Lua.
print(type(print)) --> prints 'function'
old_print = print
print = function (x) old_print "I'm ignoring the param you passed me!" end
old_print(type(print)) --> Still prints 'function' since it's still a function.
-- But we've (unhelpfully) redefined the behavior of print.
print("Hello, world!") --> prints "I'm ignoring the param you passed me!"
特別なタイプのnil
Luaの別の型はnil
です。 nil
型の唯一の値はnil
です。 nil
はLuaの他のすべての値とは異なるように存在します。これは価値のない価値の一種です。
print(foo) -- This prints nil since there's nothing stored in the variable 'foo'.
foo = 20
print(foo) -- Now this prints 20 since we've assigned 'foo' a value of 20.
-- We can also use `nil` to undefine a variable
foo = nil -- Here we set 'foo' to nil so that it can be garbage-collected.
if nil then print "nil" end --> (prints nothing)
-- Only false and nil are considered false; every other value is true.
if 0 then print "0" end --> 0
if "" then print "Empty string!" --> Empty string!
表現
a = 3
b = a + 20 a = 2 print(b, a) -- hard to read, can also be written as
b = a + 20; a = 2; print(a, b) -- easier to read, ; are optional though
true and true --> returns true
true and 20 --> 20
false and 20 --> false
false or 20 --> 20
true or 20 --> true
tab or {}
--> returns tab if it is defined
--> returns {} if tab is undefined
-- This is useful when we don't know if a variable exists
tab = tab or {} -- tab stays unchanged if it exists; tab becomes {} if it was previously nil.
a, b = 20, 30 -- this also works
a, b = b, a -- switches values
関数の定義
function name(parameter)
return parameter
end
print(name(20)) --> 20
-- see function category for more information
name = function(parameter) return parameter end -- Same as above
ブール
false
とnil
だけがfalse
と評価され、 0
を含むすべてのものと空の文字列はtrueと評価されます。
ガベージコレクション
tab = {"lots", "of", "data"}
tab = nil; collectgarbage()
-- tab does no longer exist, and doesn't take up memory anymore.
テーブル
tab1 = {"a", "b", "c"}
tab2 = tab1
tab2[1] = "d"
print(tab1[1]) --> 'd' -- table values only store references.
--> assigning tables does not copy its content, only the reference.
tab2 = nil; collectgarbage()
print(tab1) --> (prints table address) -- tab1 still exists; it didn't get garbage-collected.
tab1 = nil; collectgarbage()
-- No more references. Now it should actually be gone from memory.
これらは基本ですが、より多くの情報を持つテーブルについてのセクションがあります。
条件
if (condition) then
-- do something
elseif (other_condition) then
-- do something else
else
-- do something
end
forループ
2つのタイプがありますfor
数値:Luaのループfor
のループと、汎用for
ループが。
数値
for
ループの形式は次のとおりです。for a=1, 10, 2 do -- for a starting at 1, ending at 10, in steps of 2 print(a) --> 1, 3, 5, 7, 9 end
数値
for
ループの3番目の式は、ループが増加するステップです。これにより、逆ループを簡単に行うことができます。for a=10, 1, -1 do print(a) --> 10, 9, 8, 7, 6, etc. end
ステップ式が省略されている場合、Luaはデフォルトのステップの1を仮定します。
for a=1, 10 do print(a) --> 1, 2, 3, 4, 5, etc. end
また、ループ変数は
for
ループfor
ローカルであることにも注意してください。ループが終了しても存在しません。
Generic
for
ループは、イテレータ関数が返すすべての値を処理します。for key, value in pairs({"some", "table"}) do print(key, value) --> 1 some --> 2 table end
Luaはいくつかの組み込みイテレータ(例えば、
pairs
、ipairs
)を提供し、ユーザは独自のカスタムイテレータを定義して汎用for
ループとともに使用することができます。
ブロックを行う
local a = 10
do
print(a) --> 10
local a = 20
print(a) --> 20
end
print(a) --> 10
いくつかのトリッキーなこと
時には、Luaはドキュメントを読んだ後に思うように動作しません。これらのケースの一部は次のとおりです。
NilとNothingは同じではありません(よく陥ります!)
予想通り、 table.insert(my_table, 20)
はテーブルに値20
を追加し、 table.insert(my_table, 5, 20)
は値20を5番目の位置に追加します。 table.insert(my_table, 5, nil)
は何をしますか?引数なしでnil
を扱い、テーブルの最後に5
を挿入することが期待されますが、実際にはテーブルの5番目の位置に値nil
が追加されます。これはいつ問題ですか?
(function(tab, value, position)
table.insert(tab, position or value, position and value)
end)({}, 20)
-- This ends up calling table.insert({}, 20, nil)
-- and this doesn't do what it should (insert 20 at the end)
tostring()
同様のことが起こります:
print (tostring(nil)) -- this prints "nil"
table.insert({}, 20) -- this returns nothing
-- (not nil, but actually nothing (yes, I know, in lua those two SHOULD
-- be the same thing, but they aren't))
-- wrong:
print (tostring( table.insert({}, 20) ))
-- throws error because nothing ~= nil
--right:
local _tmp = table.insert({}, 20) -- after this _tmp contains nil
print(tostring(_tmp)) -- prints "nil" because suddenly nothing == nil
これにより、サードパーティのコードを使用する際にエラーが発生することもあります。例えば、いくつかの関数状態のドキュメントが "ラッキーならドーナツを返す、そうでないなら"と書かれていれば、実装はこれといくらか似ているかもしれません
function func(lucky)
if lucky then
return "donuts"
end
end
この実装は最初は妥当と思われるかもしれません。それが必要なときにはドーナツを返し、 result = func(false)
結果には値nil
ます。
しかし、 print(tostring(func(false)))
を書くと、luaはこのように見えるエラーをスローしますstdin:1: bad argument #1 to 'tostring' (value expected)
何故ですか? tostring
明らかに引数がありますが、それはnil
です。違う。 funcは何も返さないので、 tostring(func(false))
はtostring()
と同じで、 tostring(nil)
と同じではありません。
「価値が期待されている」というエラーは、これが問題の原因である可能性が高いことを示しています。
配列にギャップを残す
あなたがluaを初めて使う人にとってはこれは大きな落とし穴です。 テーブルのカテゴリにはたくさんの情報があります
こんにちは世界
これは世界のコードです:
print("Hello World!")
使い方?それは簡単です! Luaはprint()
関数を実行し、 "Hello World"
文字列を引数として使用します。