Lua言語をざっとペロる（for ComputerCraft）

# 前提とまえがき

ComputerCraft1.78 の lua のバージョンを調べてみたら 5.1 だった。公式では 5.2っぽいことが書いてあったけどどうなんだろ。後日調査する。ちなみ僕がやった調べ方として、コンピュータのコンソールを開き、`lua` と入力するとインタラクティブモードになる。

インタラクティブモードでのプロンプトでは、`print(_VERSION)` と入力するとバージョンは表示される

![スクリーンショット 2016-02-06 21.14.53.png](https://qiita-image-store.s3.amazonaws.com/0/9988/ea79ba25-f673-32d3-81c5-9d39c6231968.png)

インタラクティブモードを抜けるには `exit()` で。

5.1のリファレンス：[Lua 5.1 Reference Manual](http://www.lua.org/manual/5.1/)

ちなみにこの記事はCCがそのうち 5.2 になるということで Mac OS X Yosemite に 5.2 を突っ込んでソースを動かした後にサンプルソースとして書くようにしています。

## HelloWorld

行末にセミコロンがいらないデザインになってる

```lua
print("HelloWorld")
```

## コメント

ハイフン２つで行コメントが開始

```lua
-- コメント
```

複数行のコメントは --[[ と --]] を使うよ

```lua
--[[

 1. foo
 2. bar
 3. baz

--]]
```

## 変数

RubyやPHP同様宣言無しで扱える

```lua
foo = 'bar'
```

### スコープ

関数でスコープが区切られてるわけではないので（レキシカルスコープってやつかな）、関数内でローカルな変数を扱う場合は local を使う

```lua
function foo()
  bar = 'baz'
end

print(bar) --> baz
```


```lua
funcion foo()
  local bar = 'baz'
end

print(bar) --> nil
```


### 型

`type()` で調べられる。この記事では userdata型 と thread型 は扱わない

```lua
a = nil
b = 1
c = 'str'
d = true
e = function() end
f = {1, 2, 3}

--> 自作のクラスっぽいの(JSに似てる
G = {}
G.new = function(name, age)
  local obj = {}
  obj.name = name
  obj.age = age
  obj.show = function()
    print('name:'..obj.name..' age:'..obj.age)
  end
  return obj
end
g = G.new('chrowa3', 20)
g.show() --> name:chrowa3 age:20

print(type(a)) --> nil
print(type(b)) --> number
print(type(c)) --> string
print(type(d)) --> boolean
print(type(e)) --> function
print(type(f)) --> table
print(type(g)) --> table
```

## 算術演算子

| 演算子 | 説明 | 例 |
|:--|-----|:----|
| + | 加算 | 1 + 1 |
| - | 減算 | 1 - 1 |
| * | 乗算 | 1 * 1 |
| / | 除算 | 1 / 1 |
| % | 余剰 | 1 % 1 |
| ^ | 冪乗 | 1 ^ 1 |


lua にはイクリメント、デクリメントがないので ++ や -- は使えない。ってことで

```lua
i = i + 1
--だの
i = i - 1
-- だの
i = i * 2
```

だので対応


## 文字列

リテラルはシングルクォート、ダブルクォートで括る

```lua
foo = "bar"
bar = 'baz'
```

### 文字列結合

ピリオド２つでつなげる

```lua
foo = 'Hello'
bar = 'World'
print(foo..bar) --> HelloWorld
```

## 配列っぽいの（正しくはテーブル

```lua
arr = {1, 2, 3}
```

### 要素数

table.maxn() で取得できる

```lua
arr = {1, 2, 3}
length = table.maxn(arr)
print(length)
```

### インデックスは 1 から

```lua
arr = {1, 2, 3}
print(arr[0]) --> nil
print(arr[1]) --> 1
```

### テーブルは可変長配列

```lua
arr = {1 ,2, 3}
arr[4] = 4
print(table.maxn(arr))
```

### テーブルへは参照が格納

```lua
arr = {1, 2, 3}
print(arr) --> 0x7fb922409210
```

### 代入すると参照がコピーされるので副作用がある

```lua
foo = {1, 2, 3}
bar = foo

bar[1] = 10
print(foo[1]) --> 10
```

### 要素を末尾に追加 table.insert

```lua
arr = {1, 2, 3}

table.insert(arr, 4)
print(arr[4]) --> 4
```

第二引数でインデックスを指定すれば任意の場所に挿入可能

```lua
arr = {1, 2, 3}

table.insert(arr, 1, 0) --> 第二引数は挿入先のインデックス
print(arr[1]) --> 0
print(arr[4]) --> 3
print(table.maxn(arr)) --> 4
```


### 要素を末尾から取り出す table.remove

```lua
arr = {1, 2, 3}
last = table.remove(arr)

print(last) --> 3
print(table.maxn(arr)) --> 2
```

第二引数でインデックスを指定すれば任意の要素を取り出せる

```lua
arr = {1, 2, 3}
ele = table.remove(arr, 1)

print(ele) --> 1
print(table.maxn(arr)) --> 2
```


## 連想配列（正しくはテーブル

```lua
hash = {foo = 1, bar = 2, baz =3}

print(hash['foo']) --> 1
print(hash['bar']) --> 2
print(hash['baz']) --> 3
```

キーが文字列ならばドットシンタックスで参照可能

```lua
hash = {foo = 1, bar = 2, baz =3}

print(hash.foo)
print(hash.bar)
print(hash.baz)
```


## 制御文

まず条件演算子、論理演算子に触れ、if文、for文、while文にだけ触れておく

### 条件演算子

| 演算子 | 説明 | 例(true |
|:--|-----|:----|
| > | 左辺が大きければtrue | 2 > 1 |
| < | 右辺が大きければtrue | 1 < 2 |
| >= | 左辺が右辺以上ならばtrue | 2 >= 1 |
| <= | 右辺が左辺以上ならばtrue | 1 <= 2 |
| == | 同値 | 1 == 1 |
| ~= | 異なる | 1 != 2 |


### 論理演算子

| 演算子 | 説明 | 例(true |
|:--|-----|:----|
| and | 【且つ】 JS の && にあたる。 | foo and bar |
| or | 【または】 JS の &#124;&#124; にあたる | foo or bar |
| not | 【ではない】 JS の ! にあたる | ! foo |


### if文

else 以外には then を、if文の終了には end を書き、elseif とつなげるデザイン。

if - else

```lua
foo = true

if foo then
  print('foo is true.')
else
  print('foo is false.')
end

--> foo is true
```

elseif

```lua
foo = true
bar = false

if foo and bar then
  print('foo is true.')
elseif foo and not bar then
  print('foo is true. bar is false')
end

--> foo is true. bar is false
```

### for文

特徴的なのは、終了は「条件」でなく「値」。

```lua
for 初期値, 終了値, 増加量 do
  -- なんらかの処理
end
```

たとえば

```lua
for i = 0, 5, 1 do
  print(i)
end
```

では

```
0
1
2
3
4
5
```

と表示される。テーブルをループさせる場合、

```lua
arr = {'foo', 'bar', 'baz'}
len = table.maxn(arr)

for i = 1, len, 1 do
  print(arr[i])
end

--> foo
--> bar
--> baz
```

てな感じで。

### while

無限ループ

```lua
while true do
  --> infinite loop 
end
```

ループから抜けるには `break` を使う。breakは end の直前でしか使えないらしい。

```lua
while true do
  print('hoge')
  break
end

--> hoge
```

ちなみに `continue` 的なものは無いみたい。if文を駆使しましょう。


## 関数

### 定義

関数は `function 〜 end` で定義する。

```lua
function foo()
  --> 何らかの処理
end
```

呼び出しは定義後にする必要がある。Cみたい。

```lua
function hoge()
  print('hoge called.')
end

hoge() --> hoge called.
```

定義前に呼び出すとエラー

```lua
hoge()
function hoge()
  print('hoge called.')
end

lua: FunctionTest.lua:1: attempt to call global 'hoge' (a nil value)
stack traceback:
	HelloWorld.lua:1: in main chunk
	[C]: in ?
```

### 戻り値

`return` で返す。break 同様 end の直前にある必要がある。

```lua
function foo()
  return 'bar'
end

print(foo()) --> bar
```

### 引数


```lua
function twice(num)
  num = num * 2
  return num 
end

print(twice(2))
```

可変長引数

```lua
function foo(...)
  arg = {...}
  len = table.maxn(arg)
  print(len) --> 5
end

foo(1,2,3,4,5)
```

多値を戻す場合、return にカンマ区切りで返し、受け取り側で返ってきた分の変数を用意して扱う。

```lua
function foo()
  return 1,2,3,4,5
end

a,b,c,d,e = foo()
print(e)
```

とはいっても素直にテーブルで返した方がよさげ。

```lua
function foo()
  return {1,2,3,4,5}
end

bar = foo()
print(type(bar)) --> table
print(table.maxn(bar)) --> 5
```

## プロトタイプちゃん

さっきも書いたけど一応。テーブルとlocalスコープがわからないとちんぷんかんぷんになると思う。

```lua
Profile = {}
Profile.new = function(name, age)
  local obj = {}
  obj.name = name
  obj.age = age
  obj.show = function()
    print('name:'..obj.name..' age:'..obj.age)
  end
  return obj
end

chrowa3 = Profile.new('chrowa3', 20) --> name:chrowa3 age:20
chrowa4 = Profile.new('chrowa4', 30) --> name:chrowa4 age:30

chrowa3.show()
chrowa4.show()

```

ざっとこんな感じで、タートルちゃんをある程度自由に動かせるはず。記事はちょいちょい更新する。