天天看點

Lua 語言 15 分鐘快速入門

http://blog.jobbole.com/70480/

原文出處: tylerneylon   譯文出處: defsniky (@i小雨生)。歡迎加入技術翻譯小組。

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292

-

-

單行注釋

-

-

[[

[多行注釋]

-

-

]]

-

-

-

-

-

-

-

-

-

-

-

1.

變量 & 控制流

-

-

-

-

-

-

-

-

-

-

num

=

23

-

-

數字都是雙精度

str

=

'aspythonstring'

-

-

像 Python 一樣不可變

str

=

"aspythonuse"

-

-

可以雙引号

str

=

[[

像 Python 的多行注釋可用于

表示多行字元串一樣

友善

]]

bol

=

nil

-

-

未定義;支援垃圾回收

-

-

縮進隻為易讀性,像 Matlab 一樣以 end 結尾

while

num <

50

do

num

=

num

+

1

-

-

沒有

+

+

+

=

自增操作符号

end

-

-

IF 條件開關

if

num >

40

then

print

(

'> 40'

)

elseif s ~

=

'aspython'

then

-

-

~

=

表示 !

=

io.write(

's is not aspython'

)

-

-

風騷的标準輸出

else

thisIsGlobal

=

5

-

-

駝峰式命名

-

-

顯示聲明局部變量(像 Javascript 一樣)

local line

=

io.read()

-

-

.. 作為字元串連接配接符

print

(

'凜冬将至'

.. line)

end

-

-

引用未定義變量将傳回 nil ,這不是錯誤

foo

=

anUnknownVariable 

-

-

等價于 foo

=

nil

aBoolValue

=

false

-

-

隻有 nil 與 false 為邏輯假; 數字

與空字串 '' 為真!

if

not

aBoolValue then

print

(

'false'

) end

-

-

像 Python 一樣運用

'or'

'and'

-

-

得到 C 語言中 a ? b : c 的效果;需注意 b

=

false 或 nil 的情況

ans

=

aBoolValue

and

'yes'

or

'no'

karlSum

=

for

i

=

1

,

100

do

-

-

像 Matlab 一樣的遞增文法,包括兩端,如同數學中[

1

,

100

]

karlSum

=

karlSum

+

i

end

-

-

Step 為

2

遞減的方式

'100, 1, -2'

for

j

=

100

,

1

,

-

2

then

print

(j) end

-

-

綜上,範圍可表示為

"begin, end [, step]"

-

-

另一個循環控制

num

=

23

repeat

print

(

'凡人必有一死'

)

num

=

num

-

1

until num

=

=

-

-

-

-

-

-

-

-

-

-

-

2.

函數

-

-

-

-

-

-

-

-

-

-

function fib(n)

if

n <

2

then

return

1

end

return

fib(n

-

2

)

+

fib(n

-

1

)

end

-

-

Javascript 一樣的匿名函數與閉包

function adder(x)

-

-

傳回一個函數

-

-

閉包内封存 x 值

return

function (y)

return

x

+

y end

end

a1

=

adder(

9

)

a2

=

adder(

36

)

print

(a1(

16

)) 

-

-

>

25

print

(a2(

64

)) 

-

-

>

100

-

-

遇到不比對的清單長度時

-

-

過長的變量将被賦予 nil

-

-

過長的值将被忽略

x, y, z

=

1

,

2

,

3

,

4

-

-

4

将被忽略

function bar(a, b, c)

print

(a, b, c)

return

4

,

8

,

15

,

16

,

23

,

42

end

x, y

=

bar(

'zaphod'

-

-

>

"zaphod  nil nil"

-

-

x

=

4

, y

=

8

, 其餘值被忽略

-

-

函數與其他類型一樣為一等公民

-

-

同樣有 local

/

global

之分

-

-

像 Javascript 一樣定義

function f(x)

return

x

*

x end

f

=

function (x)

return

x

*

x end

print

'Hello World!'

-

-

隻有一個`字元串`參數時可省略括号

-

-

-

-

-

-

-

-

-

-

-

3.

表(Table)

-

-

-

-

-

-

-

-

-

-

-

-

表是 Lua 中唯一的複合類型

-

-

像 PHP 中的數組或 Javascript 中的

Object

一樣

-

-

可用作

list

/

dict

/

map

-

-

預設以字元串作為 key

t

=

{key1

=

'value1'

, key2

=

false}

-

-

像 Javascript 一樣以 . 取值

print

(t.key1)

-

-

>

"value1"

t.key3

=

{}

-

-

加入新的鍵值對

t.key2

=

nil

-

-

銷毀一組鍵值對

-

-

理論上任何非 nil 的變量都可以作為 key

u

=

{[

'@!#'

]

=

'qbert'

, [{}]

=

1729

, [

6.28

]

=

'tau'

}

print

(u[

6.28

]) 

-

-

>

"tau"

a

=

u[

'@!#'

]

-

-

a

=

'qbert'

b

=

u[{}]

-

-

b

=

nil;像 Javascript 一樣 {} 會建立新的對象

-

-

是以不要用蛋疼的 key 值,老老實實用字串或數字

-

-

同字元串一樣,隻有一個表作為函數的參數時可以省略括号

-

-

為了一個括号增加閱讀難度,得不償失

function h(x)

print

(x.key1) end

h{key1

=

'Sonmi~451'

-

-

>

"Sonmi~451"

for

key, val

in

pairs(u) do 

-

-

像 Python  一樣的鍵值疊代

print

(key, val)

end

-

-

像 Javascript 一樣的全局作用域 _G

print

(_G[

'_G'

]

=

=

_G)

-

-

> true

-

-

省略 key 之後即可變身為

list

-

-

實際上是以遞增自然數為 key

v

=

{

'value1'

,

'value2'

,

1.21

,

'gigawatts'

}

for

i

=

1

,

#v do  -- 像 Bash 一樣,#v 表示清單長度

print

(v[i]) 

-

-

像 Matlab 一樣,清單索引從

1

開始

end

-

-

-

-

-

-

-

-

-

-

-

3.1

Metatables & metamethods

-

-

-

-

-

-

-

-

-

-

-

-

元表(metatable)就是表的表,像 Javascript 的原型(prototype)一樣

-

-

為表重載一些元方法(metamethods)

f1

=

{a

=

1

, b

=

2

}

f2

=

{a

=

2

, b

=

3

}

-

-

s

=

f1

+

f2 為錯

mm

=

{}

function mm.__add(x, y)

sum

=

{}

sum

.a

=

x.a

+

y.a

sum

.b

=

x.b

+

y.b

return

sum

end

setmetatable(f1, mm)

setmetatable(f2, mm)

-

-

實際調用 f1 的 metatable 中的 __add(f1, f2)

-

-

隻為 f1 設定元表也可以

s

=

f1

+

f2

-

-

s

=

{a

=

3

, b

=

5

}

-

-

s2

=

s

+

s 為錯,s 未定義元表

-

-

__index 元方法重載表中 key 的提取符号 `.`

defaultFavs

=

{animal

=

'gru'

, food

=

'donuts'

}

myFavs

=

{food

=

'pizza'

}

setmetatable(myFavs, {__index

=

defaultFavs})

food

=

myFavs.food

-

-

Lua 中的值都具有元方法,隻有 Table 可以重載

-

-

所有元方法如下

-

-

__add(a, b)                    

for

a

+

b

-

-

__sub(a, b)                    

for

a

-

b

-

-

__mul(a, b)                    

for

a

*

b

-

-

__div(a, b)                    

for

a

/

b

-

-

__mod(a, b)                    

for

a

%

b

-

-

__pow(a, b)                    

for

a ^ b

-

-

__unm(a)                       

for

-

a

-

-

__concat(a, b)                 

for

a .. b

-

-

__len(a)                       

for

#a

-

-

__eq(a, b)                     

for

a

=

=

b

-

-

__lt(a, b)                     

for

a < b

-

-

__le(a, b)                     

for

a <

=

b

-

-

__index(a, b)  <fn

or

a table> 

for

a.b

-

-

__newindex(a, b, c)            

for

a.b

=

c

-

-

__call(a, ...)                 

for

a(...)

-

-

-

-

-

-

-

-

-

-

-

3.2

類風格的 Table 與繼承

-

-

-

-

-

-

-

-

-

-

-

-

像 Javascript 一樣并沒有内置 Class

-

-

但可以通過 Table `{}` 實作

Dog

=

{}                               

-

-

1.

function Dog:new()                     

-

-

2.

newObj

=

{sound

=

'woof'

}          

-

-

3.

self

.__index

=

self

-

-

4.

return

setmetatable(newObj,

self

)  

-

-

5.

end

function Dog:makeSound()               

-

-

6.

print

(

'I say '

..

self

.sound)

end

mrDog

=

Dog:new()                      

-

-

7.

mrDog:makeSound()

-

-

>

"I say woof"

-

-

1.

Dog 像類但實際是 Table

-

-

2.

Dog:new(...) :

=

Dog.new(

self

, ...)

-

-

3.

newObj 作 Dog 的執行個體

-

-

4.

self

是 Lua 中預設的參數,在這裡

self

=

Dog

-

-

繼承的時候可以改變

-

-

self

.__index 與

self

的元方法 __index 不是一回事

-

-

self

=

{__index

=

self

, metatable

=

{__index

=

...}}

-

-

5.

setmetatable(newObj,

self

) 相當于 setmetatable(newObj, {__index

=

self

})

-

-

賦予執行個體所有類方法

-

-

6.

2.

-

-

7.

mrDog

=

Dog.new(Dog)

-

-

繼承

LoudDog

=

Dog:new()

function LoudDog:makeSound()

s

=

self

.sound ..

' '

print

(s .. s .. s)

end

seymour

=

LoudDog:new()

seymour:makeSound()

-

-

>

"woof woof woof"

-

-

-

-

-

-

-

-

-

-

-

4.

子產品

-

-

-

-

-

-

-

-

-

-

-

-

以下來自檔案 mod.lua

local M

=

{}

local function sayMyName()

print

(

'Hrunkner'

)

end

function M.sayHello()

print

(

'Why hello there'

)

sayMyName()

end

return

M

-

-

以上

-

-

回到主檔案

local mod

=

require(

'mod'

)

-

-

運作 mod.lua 中的代碼

-

-

操作同下

local mod

=

(function()

-

-

像 Javascript 一樣

-

-

[[

mod.lua 中的代碼

]]

-

-

end)()

mod.sayHello()

-

-

>

"Why hello there"

mod.sayMyName()

-

-

> 錯!sayMyName() 是 mod.lua 中的局部變量

-

-

require 傳回的值将被緩存

-

-

即使多次調用 require 被調用檔案也隻運作一次

-

-

mod2.lua 包含

print

(

"mod2"

)

local a

=

require(

"mod2"

)

-

-

>

"mod2"

local b

=

require(

"mod2"

)

-

-

不輸出, 實際為 b

=

a

-

-

dofile 是不緩存的版本的 require

dofile(

"mod2"

)

-

-

>

"mod2"

dofile(

"mod2"

)

-

-

>

"mod2"

-

-

loadfile 讀取檔案但不執行

-

-

勘誤:f

=

loadfile(

'mod2'

),需加字尾名,否則找不到檔案

f

=

loadfile(

'mod2.lua'

)

f()

-

-

>

"mod2"

-

-

loadstring 讀取代碼字元串

f

=

loadstring(

"print('Lua is cool!')"

)

f()

-

-

>

"Lua is cool!"

-

-

-

-

-

-

-

-

-

-

-

5.

參考,略

-

-

-

-

-

-

-

-

-

-

後記:

感覺 Lua 才應該是學完 C 語言之後最先學習的語言,因為它本身就是一個非常優秀的純粹由 C 語言完成的項目,尤其是對于非計算機專業出身又想要學習計算機原理相關的東西,甚至可以嘗試閱讀 Lua 源碼;因為其内容簡潔而又五髒俱全,相比于其它進階語言對基本資料類型的複雜操作、複雜的文法結構等,Lua 15 分鐘入門應該會比《21天精通XXX》更現實一些吧

:)

- END -

lua