Lua 是怎樣一門語言?
全部回答:
https://www.zhihu.com/question/19841006
皮皮關(guān)的回答:
https://www.zhihu.com/question/19841006/answer/1432644108
以下內(nèi)容為對知乎答主皮皮關(guān)內(nèi)容的搬運(yùn)(部分對Aegisub開發(fā)比較核心的地方會用紅色標(biāo)注):
首先,Lua是一種在游戲開發(fā)領(lǐng)域非常常用的語言。
(1)魔獸世界客戶端、大話西游2等知名網(wǎng)游中有Lua的身影。
(2)現(xiàn)代眾多熱更新手游也常用Lua寫游戲邏輯,便于做熱更新。
(3)Lua在skynet等現(xiàn)代網(wǎng)絡(luò)游戲框架中有廣泛應(yīng)用。
1、Lua很小,語法極精簡,但功能一點(diǎn)不少
Lua用純C語言編寫而成,兼容極為多樣的平臺包括某些單片機(jī)平臺。
整個Lua語言的C語言源代碼僅有2萬行出頭,這2萬行代碼包含了完整的編譯器、虛擬機(jī)等等。
Lua僅有21個關(guān)鍵字。相比之下,連老版本(C89)的C語言都有32個關(guān)鍵字。
在如此精簡的語法基礎(chǔ)上,Lua實現(xiàn)了過程式編程、函數(shù)式編程、面向?qū)ο缶幊蹋òǚ庋b、繼承和多態(tài))等等常用編程范式,且對閉包與協(xié)程都有極為完善的實現(xiàn)。
2、Lua語法過于靈活,不宜作為第一門編程語言學(xué)習(xí)
Lua實現(xiàn)了眾多神奇功能的背后,離不開“表”(Table)這種數(shù)據(jù)結(jié)構(gòu),以及一些奇妙的設(shè)計。舉一些例子:
(1)在Lua中,未使用過的變量值為nil
我們知道,絕大多數(shù)語言讀取未定義或未使用過的變量,都會報錯。但Lua不會,所有的變量初次讀取不會報錯,值為nil。
寫錯變量名是人之常情,對新手來說找手誤bug是一種挑戰(zhàn) ?:)
(2)在Lua中,不加local關(guān)鍵的變量默認(rèn)是全局變量
在實踐中,建議給所有變量加上local,除非你確認(rèn)一定需要全局變量。不加local所造成的奇怪bug會讓你終身難忘 ?:)
(3)lua的邏輯運(yùn)算符and、or
lua中,邏輯為假的值只有兩個:nil和false;其它所有值包括數(shù)字0,都是真。
A and B:如果A為真,返回B;如果A為假,返回A。
A or B:如果A為真,返回A;如果A為假,返回B。
這種設(shè)計會讓不熟悉邏輯運(yùn)算的同學(xué)一頭霧水,但邏輯上是自洽的。Lua的這種設(shè)計帶來一些巧妙的用法:
(4)神奇的Lua Table
Lua的table容器是一種萬能容器,可以用來作為:
①列表
②字典
③嵌套的列表和字典
④程序集(庫)
⑤對象
在基本的表操作中,加入元表(metatable)之后,能支持更多特性:
①類的繼承
②多態(tài)
③多重繼承
元表是一種極為靈活的語法,利用元表甚至能修改Lua的基本語義,例如改變賦值的作用。
從教學(xué)的角度講,Lua不宜作為第一門編程語言。但在有一定編程基礎(chǔ)以后,通過類比學(xué)習(xí)Lua能起到舉一反三的效果~~~
3、Lua具有極為優(yōu)良的嵌入特性
(下面的內(nèi)容是之前另一個問題的答案,比較有價值所以摘抄如下。參考原鏈接:https://www.zhihu.com/question/21717567/answer/229327361)
下面我會揭示游戲程序框架與Lua關(guān)系一個關(guān)鍵的方面。
和所有人一樣,我曾經(jīng)認(rèn)為所有腳本語言能嵌入到引擎中都是一樣的。直到引擎架構(gòu)足夠復(fù)雜的時候,才發(fā)現(xiàn)了區(qū)別。在將腳本嵌入到本身就要處理多進(jìn)程、多線程的框架之中時,腳本本身的架構(gòu)會造成根本性差異,以下討論都是針對這一點(diǎn)說的。
首先對比一下Lua和Python的代碼規(guī)模:
(1)Python完整C語言代碼,約57萬行
(2)Python核心C語言代碼,約17萬行
(3)Lua的所有C語言代碼,約2萬行
放心,我不是來說Lua有多么簡潔多么美妙,問題不在這里。問題是:為什么Lua這么短?
任何一種程序,它所包含的邏輯功能大致和源碼規(guī)模是相關(guān)的。任何一種實用性的語言都不可能比Lua的源碼規(guī)模更小,而且未來Lua也不會變大很多,原因是——Lua嚴(yán)格限制了自己要解決的問題,從而把語言特性限制在一個非常有限的范圍之內(nèi)。
其實要說Python等其它動態(tài)語言,誰也沒想讓自己變得臃腫(又不是Windows),但是事情并不總能按照想象的發(fā)展。根源在于虛擬機(jī)的框架設(shè)計主導(dǎo)了語言未來的走向,這里比較一下在C語言中初始化Python和Lua的方法:
初始化Lua環(huán)境(2個獨(dú)立環(huán)境):
初始化Python環(huán)境:
看看注釋,區(qū)別顯而易見。大部分語言的虛擬機(jī)設(shè)計的目的是為了直接解決實際問題的,所以希望虛擬機(jī)能夠獨(dú)立運(yùn)行,這就與線程、進(jìn)程等等操作系統(tǒng)功能發(fā)生了直接聯(lián)系。
比如Python環(huán)境就直接是全局變量,導(dǎo)致你無法在C里面優(yōu)雅地使用一個沙盒式的Python環(huán)境,也就是說Python環(huán)境和C代碼的部分理論上來講是毫無分隔的。
而Lua虛擬機(jī),不準(zhǔn)確的說,和線程、進(jìn)程關(guān)系都不大,一開始就把自己摘的干干凈凈,沒規(guī)定1個進(jìn)程只有一個Lua虛擬機(jī),也沒規(guī)定一個線程只執(zhí)行一個Lua虛擬機(jī),X個進(jìn)程Y個線程Z個虛擬機(jī)你想怎么來就怎么來,一切都根據(jù)你的需求來設(shè)計即可(實際設(shè)計時只需要搞清楚ENV問題即可)。
說到這里必須提一下skynet(一種高性能通用服務(wù)器框架),skynet就是對Lua虛擬機(jī)一種很高級的應(yīng)用,每次給別人介紹skynet的“微服務(wù)”與Lua虛擬機(jī)的關(guān)系,都要費(fèi)不少口舌而且說不清楚,原因就是我們大部分人對進(jìn)程、線程、虛擬機(jī)的關(guān)系有一些不準(zhǔn)確的、先入為主的概念。
Lua所有API的設(shè)計,都帶有上面的lua_State* L參數(shù),這就用無副作用的方式讓Lua成為了一種非常非常非常適合嵌入的語言。無論你的框架是如何復(fù)雜,你總能找到一種簡單的嵌入Lua的方式而且對框架沒什么影響。
以上例子都說的是服務(wù)器框架,因為服務(wù)器框架一般邏輯架構(gòu)比較復(fù)雜。其實由于多線程和并發(fā)難題的存在,未來的客戶端邏輯框架也會有復(fù)雜化的趨勢,例如Actor、ECS等新的架構(gòu)也會用在客戶端,這種情況下Lua的優(yōu)勢也同樣會體現(xiàn)出來。
當(dāng)然,也是基于同樣的原因,skynet這種高并發(fā)框架很難修改為除Lua以外的其他語言的版本。
如果你恰好熟悉Python語言,那么正好可以對比一下所謂GIL(Python全局鎖)的問題,在理解了Lua的設(shè)計思路之后,你就大概能猜到為什么從來沒有人提Lua的全局鎖了,因為這個問題本身就不存在。
大概意思就說到這里吧,可以在評論中繼續(xù)探討。至于Lua速度快、小巧等等其他特點(diǎn),也都是Lua廣泛流行的原因的一部分。
感謝這種神奇的小語言。