Luaのチュートリアルやってみた

結構前に買ったエキスパートPythonプログラミングですが、案の定当時の自分にはちょっとレベルが高かったので寝かせてたのですが最近また再開してます。それで、コルーチンを実装するってところがよくわかんなかったので、ネイティブでコルーチンを実装してるLuaをやってみようと思い立ったのでした。

以下、自分用の備忘録ですがせっかくなので公開用にまとめてみました。
といってもチュートリアル自体はめちゃめちゃ簡単です。問題は自分の編集能力の低さですね。

Windowsへのインストール


luaforwindows -


Installation of Lua for the Windows operating systems including many lua libraries. - Google Project Hosting
から「LuaForWindows_v5.1.4-40.exe」をダウンロードしてインストールするだけ。
インストール終了後にチュートリアルをやるかどうか聞かれますが、これは「Lua\5.1\examples\quickluatour.lua」のことなので、先に付属のエディタに日本語周りの設定をしちゃいます。
(スタートメニューにもこのチュートリアルは登録されてると思います)

SciTE(エディタ)の設定

Luaと一緒にSciTEというLua用のエディタがインストールされてますが、デフォルトだと日本語が文字化けします。設定ファイルを編集擦る必要がありますがすぐ終わります。

SciTEのメニューの[Options]-[Open Global Options File]で開いたファイルの292行目以下にこのような記述があります。

# Internationalisation
# Japanese input code page 932 and ShiftJIS character set 128
#code.page=932
#character.set=128
# Unicode
#code.page=65001
code.page=0

Japanese input〜という感じで最初から日本語の為の設定がコメントアウト状態で記述されてるのでコメント文字(#)をはずします。
あわせてUnicodeの方の記述をコメントアウトします。

# Internationalisation
# Japanese input code page 932 and ShiftJIS character set 128
code.page=932
character.set=128
# Unicode
#code.page=65001
#code.page=0

設定はこれだけです。

チュートリアルやってみたのでまとめ

--print関数
print('hello') --hello

-- 一行コメント
--[[
複数行コメントは
このように書くらしい
]]

--型
a=1
b="abc"
c={}
d=print

print(type(a)) --number
print(type(b)) --string
print(type(c)) --table
print(type(d)) --function

--変数
--[[変数に使えるのは英数字およびアンダースコアのみ。
変数の頭を数字ではじめることはできない]]
one_two_3 = 123 --これはOK
1_two_3 --これはエラー

--[[組み込み変数にはアンダースコアで始まるものが存在するけど、
_ ←こういう_だけの変数はダミー変数としてしばしば用いられる
print(_VERSION) --Lua 5.1
_ = 123 --ダミー変数

--[[変数のアルファベットの大文字と小文字を区別される
以下の変数はそれぞれ別の変数として扱われる]]
ab=1
Ab=2
AB=3
print(ab,Ab,AB) -- 1 2 3

--予約語一覧
and break do else elseif end false for function if in
local nil not or repeat return then true until while

--[[ただし、andは予約語なので変数に使えないが、ANDはandとは区別されるので
変数として使用することができる]]
AND=3
print(AND) --3

--エスケープシーケンスと複数行文字列
a="single 'quoted' string and double \"quoted\" string inside"
b='single \'quoted\' string and double "quoted" string inside'
c= [[ multiple line
with 'single'
and "double" quoted strings inside.]]

--多重代入
a,b,c,d,e = 1, 2, "three", "four", 5

--値の交換もできる
a,b=b,a

--文字列の連結にはドットを2つ並べたもの(..)を使う。
a,b,c,d,e = 1, 1.123, 1E9, -123, .0008
print("a="..a, "b="..b, "c="..c, "d="..d, "e="..e)
--a=1 b=1.123 c=1000000000 d=-123 e=0.0008

--[[
ちょっとex12の意味がわからなかった。
More Output.
More writing output.
って書いてたけどわからなかったので色々試した結果、
文字列以外(数値やテーブルなど)をprintしようとすると
エラーになった。文字列なら
"文字列"
にも
[[



]]
にも括弧は要らない。
]]

print "Hello from Lua!"
print("Hello from Lua!")

--[[
printとは別にio.writeメソッドがある。
これは末尾に改行文字が含まれない。
]]
io.write("Hello from Lua!")
io.write("Hello from Lua!")
--Hello from Lua!Hello from Lua!
print() --空行を作成する

--テーブル
a={} -- {}で空のテーブルを作成
b={1,2,3} -- 数値の入ったテーブル
c={"a","b","c"} -- 文字列の入ったテーブル
print(a,b,c) -- テーブルは直接出力されない
--table: 00410C80 table: 004110B8 table: 004111E0

--[[テーブル名.キー名 = 値 のようにして
テーブルに要素を追加]]
address={}
address.Street="Wyman Street"
address.StreetNumber=360
address.AptNumber="2a"
address.City="Watertown"
address.State="Vermont"
address.Country="USA"

print(address.StreetNumber, address["AptNumber"])
--360 2a

--if文
a=1
if 条件 then
    ブロック
elseif 条件 then
    ブロック
else
    ブロック
end

--多項式
a=1
b=(a==1) and "one" or "not one"
print(b)
--これは
a=1
if a==1 then
    b = "one"
else
    b = "not one"
end
print(b)
--と等価とのこと。

--while文
while 条件 do
    ブロック
end

--repeat〜untile文。
--他言語のdo〜while文と同じものかと。
--[[
(追記)
ちょっと勘違いしてました。
do〜whileみたいに必ず1度はブロックが実行されるのは同じですが
条件が「偽」の間ループし続けるようです。
]]
repeat
    ブロック
until 条件


--for文
--[[数値用と汎用の二つがある
数値用 for Name=exp1,exp2[,exp3] do block end
汎用   for Name {, Name} in explist1 do block end
それぞれ多言語でいうfor文とforeach文のことかと。]]

--1から4までを1ずつ
for a=1,4 do io.write(a) end
--1234

--1から6までを3ずつ
for a=1,6,3 do io.write(a) end
--14

--汎用のほう
for key,value in pairs({1,2,3,4}) do print(key, value) end
--[[
1	1
2	2
3	3
4	4
]]

a={1,2,3,4,"five","elephant", "mouse"}
for i,v in pairs(a) do print(i,v) end
--[[
1	1
2	2
3	3
4	4
5	five
6	elephant
7	mouse
]]

--ループを抜けるにはbreak
a=0
while true do
    a=a+1
    if a==10 then
        break
    end
end
print(a)
--10

--関数
function MyFirstLuaFunction()
    print("My first lua function was called")
end

myFirstLuaFunction()
--My first lua function was called

--[[
EX27はreturnで値を返す例でした。
尚、ここでの例は引数を取らない関数に引数を渡して呼び出してたんですが、
エラーにならずに普通に処理された事にちょっとビックリ。
function f() return "hoge" end print(f(100)) 
がエラーにならないで"hoge"が出力されるのはちょっと気持ち悪い
]]

--returnで複数の値を返すことも可能。
function myFunction(1,2,"three")
	return a, b, c
end

x, y, z = myFunction(1, 2, 3)
print(x, y, z)

--変数のスコープについて
--[[
全ての変数のスコープはグローバル。
ローカル変数を定義するには変数名の前にlocalを付けて
ローカル変数であることを明示する。
]]
b="global"
function myfunc()
	local b="local variable"
	a="global variable"
	print(a,b)
end

myfunc()
print(a,b)


--可変引数は ...
function printf(fmt, ...)
	io.write(string.format(fmt, ...))
end

printf("Hello %s from %s on %s\n",
	os.getenv"USER" or "there", _VERSION, os.date())
--Hello there from Lua 5.1 on 05/14/11 16:16:40

--[[
あとは標準ライブラリをすごく大雑把に紹介されてチュートリアルは終了しました。
最後のex37ではiupluaというGUIツールキットの紹介なんですが、
なんだかファイルが足りないようでエラーになってました。
http://blog.livedoor.jp/take_z_ultima/archives/51682103.html
↑こちらを参考にiup.dllとiuplua51.dllを入れたらちゃんと動きました。
]]

とまあこんな感じでチュートリアルは終了しました。

Luaがコンパクトな言語とは言ってもこれだけじゃいろいろ足りない(コルーチン出てこない)ので次はLua 5.1 ¥ê¥Õ¥¡¥ì¥ó¥¹¥Þ¥Ë¥å¥¢¥ëあたりを参照してみようかなと思います。あとはLuaインストールフォルダ内のexamplesフォルダにサンプルがたくさん入ってたのでそっちもチェックしてみようっと。

(追記)関数呼び出しの括弧について

ブコメで「Lua では、関数の引数が1個の文字列/1個のテーブルの時、関数コールの括弧を省略することができる。print に限った話ではない。」と教えていただいたのでリファレンスを見てみました。

引数は以下の構文を持つ。

args ::= `(´ [explist1] `)´
args ::= tableconstructor
args ::= String

引数のすべての式は呼び出し前に評価される。 f{...} は f({...}) のシンタックスシュガーであり、新しいテーブルひとつが引数となる。 f'...' (および f"..." や f...) は f('...') のシンタックスシュガーであり、引数は文字列リテラルひとつである。
Lua 5.1 ¥ê¥Õ¥¡¥ì¥ó¥¹¥Þ¥Ë¥å¥¢¥ë

シンタックスシュガーだったのか。関数の引数がテーブル(文字列)ひとつだけの場合、括弧を省略しても内部的に括弧付きの構文へ変換してくれるようです。