2016年1月27日 星期三

Lua: 撰寫函式庫

在Lua中要寫一個library給別人使用可以依以下寫下法處理

在my_module.lua中程式為:
local myMod = {}

function myMod.add(a, b)
    return (a+b)
end

function myMod.dot(a, b)
    return (a*b)
end

return myMod

在主程式中則可以這樣引用
local myMod = require("my_module")

print(myMod.add(10, 20))
print(myMod.dot(3, 5))
print(myMod.add(2, myMod.dot(3, 4)))

require()用來把需要的library引入

若想要寫成像物件那樣好像也可以使用module的方式處理…現在還沒讀到,晚點再介紹這部份

另外,還可以幫模組(或是說變數)動態增加function
local myMod = require("my_module")

function myMod.print(a, b)
    print("value=", a, b)
end

function myMod:print2(a, b, c)
    print("value2=", a, b, c)
end


print(myMod.add(10, 20))
print(myMod.dot(3, 5))
print(myMod.add(2, myMod.dot(3, 4)))

myMod.print(11, 22)
myMod.print2(111, 222, 333, 444)
--[[結果為
30
15
14
value= 11 22
value2= 222 333 444
]]

這邊還不是很懂「.」和「:」的差異…
由網路查來的說法是
function myMod:print2(a, b, c)
等同於  function myMod.print(self, a, b, c)
多了一個把自己當成引數
因此把第二個function改為
function myMod:print2(a, b, c)
    print("value2=", a, b, c)
    print('type=', self)
end

myMod.print(111, 222, 333, 444)
則會印出
value2= 222 333 444
type= 111




2016年1月24日 星期日

Lua: String

之前有提到在做一些自訂或別人定義的protocol時會常需要使用string來組一些binary資料,因此string的各種操作就顯示蠻重要的

-----
string.byte  字串轉為byte array table
print(string.byte("abcde"))  --> 97
print(string.byte("abcde", 3))  --> 99 也就是 'c'
print(string.byte("abced", 2, 4))  --> 98 99 101


------
string.char()  --> 這是最重要,目前最常用的

string.char(0, 65)
--> 得到的一個string,由binary的0, 65組成 (注意是10進制的!)

------
string.len(str)  取得字串長度

------
string.rep( s, n )  也是個方便常用的東西,測試要填重複資料時蠻好用的
print(string.rep("123_", 4))
--> 結果 123_123_123_123_

------
string.sub( s, i [, j] )

print(string.sub("abcde", 3, 4))
-->結果為 cd


------
string.upper(str)  / string.lower(str)
即全變大寫 / 小寫

---------
string.find( s, pattern [, init [, plain], ] )
--> pattern 的表示方式應該蠻重要的,晚一點再多寫點範例

print(string.find("abc_123", "abc"))  --> 1 3   回傳找到字串的起始index、結束index
print(string.find("abc_123", "abc", 3)) --> nil   從index=3開始找,找不到就回傳 nil

--------
string.format( formatstring [, ...] )

print(string.format('%d, %x, %X, %.4f', 10, 10, 10, 10/3))
--> 10, a, A, 3.3333

-------
string.match( s, pattern [, init] )    在s中找pattern是否在,若有就回傳些相符的string

print(string.match('time is 2015/10/3 12:15:30', '%d+/%d+/%d'))
--> 得到 2015/10/3

-------
string.gmatch( s, pattern )   疊代回傳所有相符的string
還不是很會用,先寫個範例
str = "it a big apple"
for item in string.gmatch(str, '%a+') do
    print(item)
end
--[[回傳結果
it
a
big
apple
]]






Lua: Table

Table 是很重要的,因此另外記下它的用法!

Table的索引可以是 nil外的任何類型的變數,當然最常用的還是number和string
先來個例子比較好理解
> t = {
>> name = "jeff",  --> 可以理解為使用string當成取值的key
>> phone = {'09123456', '04-2222333'},  -->一樣,但值改為另一個table
>> email = 'abc@gmail.com',
>> 60, --kg  --> 不指定index key,因此為流水號,為[1]
>> 170, --cm  --> 不指定index key,因此為流水號,為[2]
>> [5] = 'apple'  --> 指定為[5]
>> ,
>> ['sport'] = 'football'
>> }
> print(t.name, t.phone, t.email)  -->第二個因為是table,所以印出來的是table的address
jeff    table: 004346C0 abc@gmail.com
> print(t[1], t[2], t[3], t[4], t[5])   -->因為只有[1], [2], [5]有值,所以其它的為nil
60      170     nil     nil     apple
> print(t['sport'], t.phone[1])
football        09123456
> print(t.sport)  -->這裡就更重要了,可看.sport和['sport']是等效的
football
> print(t['name'])  -->反過來也OK
jeff
> print(t.5)  --> 但是數字的index不能使用.5的方式的表示
stdin:1: ')' expected near '.5'

這邊可以看出一個現象:Lua的index是由1算起的,比較像basic不像C


--------------
取得元素的個數,這就讓我疑惑了…
> print(table.getn(t))
2

可以了解,getn()只會取得以number為index key的元素數量,且從1開始算起,直到nil為止!!
因為t[3]是nil,所以被判定為只有2個元素
--> 要很小心,不要在 Table中隨便的使用 nil,如果這一個元素真的用不到就直接remove掉

--------------
concat 把所有元素結合在一起,是個很方便的用法,等於是把所有元素都用..連起來

> t2 = {1, 2, 3, "44"}
> print(table.concat(t2))
12344
> print(table.concat(t2, ", "))
1, 2, 3, 44
> print(table.concat(t2, " ", 2, 4))
2 3 44

---------------
insert(table, [index, ] value)

> print(table.concat(t2, " ", 2, 4)
> print(table.concat(t2, ", "))
11, 1, 2, 3, 44
> table.insert(t2, 99)
> print(table.concat(t2, ", "))
11, 1, 2, 3, 44, 99

-----------------
remove(table, index)

> table.remove(t2, 1)
> print(table.concat(t2, ", "))
1, 2, 3, 44, 99

-------------------
maxn(table) 取得最大的index
> print(table.maxn(t2))
5

###!!! 要注意的,之前提到的nil的事,以下的操作並不會讓max index增加!,因此說這用法很方便,但很有陷井

> table[7] = 7
> print(table.concat(t2, ", "))
1, 2, 3, 44, 99
> print(table.maxn(t2))
5

-------------------
sort(table [, compare])

local t = {1, 2, 7, 5, 3}
table.sort( t )
print(table.concat(t, ", "))
--> 1, 2, 3, 5, 7

local function compare(x, y)
   return x > y
end

table.sort(t, compare)
print(table.concat(t, ", "))
-->7, 5, 3, 2, 1


2016年1月23日 星期六

Lua: Function

function的基本寫法

function max(a, b)
  if(a>b) then return a
  else return b
  end
end

print(max(10, 20))
--> 印出來的結果為 20

但如果這樣寫就會出錯,還不清楚為何…
> local function max(a, b)
>> if(a>b) then return a
>> else return b
>> end
>> end
> print(max(10, 20))
stdin:1: attempt to call global 'max' (a nil value)
stack traceback:
        stdin:1: in main chunk
        [C]: ?


因為function都是以「傳值」的方式在處理參數,因此會有以下的結果
> function func1(a, b)
>> local tmp = a
>> a = b
>> b = tmp
>> print("change in function:", a, b)
>> end
> x = 1
> y = 2
> func1(x, y)
change in function:     2       1
> print(x, y)
1       2

當傳入function的參數較function定義的參數多時基本上不會有問題,系統會把多的拿掉
> function func2(a, b)
>> print(a, b)
>> end
> func2(1, 2)
1       2
> func2(1, 2, 3, 4)
1       2

又或傳入的參數較function定義的參數少時也不會有問題,系統會自動補 nil進來
> function func3(a, b, c, d)
>> print(a, b, c, d)
>> end
> func3(1, 2)
1       2       nil     nil

不固定數量的function參數雖然說可以用,但是我的Lua卻是error的
> funcation func4(...)
stdin:1: '=' expected near 'func4'




Lua: 流程控制

for  --> 一般的用法

--> 印出1~5的數字
for i=1, 5 do
  print(i)
end

--> 印出1, 3, 5, 7, 9,第三個參數step也可以是負數
for i=1, 10, 2 do
  print(i)
end

for  --> 像 for...each的用法 (iterator)

a = {'a', 'b', 'c', 'd'}
for i, v in ipairs(a) do
  print('index('..i..') = '..v)
end
--[[ 結果印出如下
index(1) = a
index(2) = b
index(3) = c
index(4) = d
]]

而使用 pairs也是一樣的結果? --> 這個再查一下…
for k,j in pairs(a) do
  print(k, j)
end
--[[ 結果如下
1       a
2       b
3       c
4       d
]]

while
語法為
x=1
while x<5 do
  x=x+1
  print(x)
end
--[[結果如下
2
3
4
5
]]

可以用 break 跳出迴圈,但沒有continue ?

此外也有repeat的loop寫法,不過我想固定使用一種就好了,免的搞亂了…畢竟有時才寫一下Lua而已,簡單是王道
repeat
  x=x+1
  print(x)
until (x>5)
--[[結果為
2
3
4
5
6
]]

if...then...else...end
例子如下
if(5>3) then
  print(5)
else
  print(3)
end
--> 結果為 5

也有elseif的用法
x = 70
if(x>90) then print(">90")
elseif(x>60) then print(">60")
else print("<60")
end
--> 60



Lua: 運算子

算數運算子
+ : 加
- : 減
* : 乘
/ : 除
% : mod, 模數
^ : power,指數運數

> print(10%3)
1
> print(10^3)
1000

關係運算子
> 大於, < 小於, >= 大於等於, <= 小於等於, == 等於, ~= 不等於
例如:
> print(3>4)
false
> print(4~=5)
true

邏輯運算子

and, or, not -->這應該不用說明就很明白了

但Lua中的這類運算子和其它語言是完全不同的喔!

and: 在lua中是沒有遇到false就一直往右找,直到false出現,再回傳,若沒有false就回傳最後一個值

or :在lua中是沒有遇到true就往右找,直到true出現


因此有以下的結果:

print(1 and 3 and 5) --> 印出 5

print(abc and 1) --> 印出nil,因為abc未用過,為nil

print(abc or 1) --> 印出 1,因為nil是false,而1是true,所以把1回傳


Lua start



Lua的預備資料,先memo一下

1、Lua各版本是不相兼容的… --> 目前我使用的Lua是5.1.x

2. LuaJIT vs Lua --> 因有人覺得Lua不夠快,因此使用Just-in-time的技術再把速度榨出來!

接著就是基本語法、變數型態的說明了

3. 變數有:
nil: 像c裡的null
> local aa
> print aa
stdin:1: '=' expected near 'aa'
> print(aa)
nil
> aa = 10
> print(aa)
10

boolean: 有true, false
這比較特別,只有nil和false是假,其它都是真,不同於其它語言!
> a = true
> print(a)
true
> if a then
>> print("true")
>> else
>> print("false")
>> end
true
> b = 0
> if b then
>> print("true")
>> else
>> print("false")
>> end
true


number: 只使用double表示和其它程式語言差不多,就不多說了

string: 可用二種表示方式 'string' 或是 "string",和python中的string一樣不可變動內容,只能再長一個新的。
多個string用..接起來,如
> print("aaa".."bbb")
aaabbb

在寫protocol時常會需要用到binary的表示方式,可以
'Local IO'..string.char(0, 10) --> 把Local IO字串後加上binary的0和10


table: -->好像很多技術都是用這東西做的,晚點懂了再寫

function: 咦! function也是,這還蠻特別的
--> 一邊看一邊學一邊記,來綠是這裡

另一本書是寫有八種: eight basic types in Lua: nil, boolean, number, string, function, userdata, thread,and table.
( 由Lua 5.0 Reference Manual來的說法)


4. 註解表示方式
-- 是註解
--[[
多行註解
]]