Looking for lua Answers? Try Ask4KnowledgeBase
Looking for lua Keywords? Try Ask4Keywords

LuaLuaを使い始める


備考

ルアのロゴ

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の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
 

ブール

falsenil だけが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はいくつかの組み込みイテレータ(例えば、 pairsipairs )を提供し、ユーザは独自のカスタムイテレータを定義して汎用for ループとともに使用することができます。

ブロックを行う

local a = 10
do
    print(a) --> 10
    local a = 20
    print(a) --> 20
end
print(a) --> 10
 

こんにちは世界

これは世界のコードです:

print("Hello World!")
 

使い方?それは簡単です! Luaはprint() 関数を実行し、 "Hello World" 文字列を引数として使用します。

インストール

バイナリ

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 を指定しました。その他の使用可能なビルドターゲットには、 solarisaixbsdfreebsdmacosxmingw などがあります。詳細は、ソースに含まれているdoc/readme.html 参照してください。 ( 最新のREADMEもオンラインで入手できます 。)

モジュール

標準ライブラリはプリミティブに限定されています。

  • coroutine - コルーチン管理機能
  • debug - デバッグフックとツール
  • io - 基本IOプリミティブ
  • package - モジュール管理機能
  • string 列とLua固有のパターンマッチング機能
  • table - 本質的だが複雑なLuaタイプを扱うためのプリミティブ - テーブル
  • os - 基本的なOS操作
  • utf8 - 基本的なUTF-8プリミティブ(Lua 5.3以降)

これらのライブラリはすべて、特定のビルドのために無効にすることも、実行時にロードすることもできます。

モジュールを配布するための第三者のLuaライブラリとインフラストラクチャはまばらですが、改善しています。以下のようなプロジェクトLuaRocksLuaのツールボックス 、およびLuaDistは 、状況を改善しています。多くの情報と多くの提案が古いLua Wikiで見つかることがありますが、この情報のいくつかはかなり古いものであることに注意してください。

いくつかのトリッキーなこと

時には、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を初めて使う人にとってはこれは大きな落とし穴です。 テーブルのカテゴリにはたくさんの情報があります