學習 Lua 對於了解 Javascript 的人來說就是小菜一碟,Tyler Neylon 寫了三篇文章來解釋其中的原因,這是其中的第一篇。
這是通過 Javascript 來學習 Lua 系列文章的第一篇,一共有三篇,第二篇和第三篇。
登陸 Tyler 的免費的網絡廣播頻道收聽 Lua 能做什么?
Lua 是一門優雅的,可移植的,高效的並且異常靈活的語言。所有能夠編譯 C 語言的操作系統都能運行 Lua,這是一些跨平台的框架,比如 Corona SDK 和 Love game engine,選擇 Lua 的原因。Lua 的運行速度很快,足夠用來開發游戲——憤怒的小鳥的最初是用 Lua 編寫的。 Lua 能和其他的語言很好的融合在一起,它作為腳本語言,在 Adobe lightroom 項目中有出色的表現。我認為 Lua 的設計很優美,用起來也非常的舒服。
對於已經了解 Javascript 的人而言,學習 Lua 是非常簡單的,因為Lua 和 Javascript 有很多的共同點。在學習的過程中,我們可以通過這些共同點很快的熟悉 Lua,但需要注意兩者間一些關鍵性的不同的地方。
通過 Javascript 的相關知識學習 Lua 的系列總共三篇,這是其中的第一篇。這篇文章中包含一些基礎概念:安裝 Lua,變量,數據類型,操作符和表達式。第二篇將會涉及流程控制和數據結構,第三篇講解對象相關的一些知識。
文章中出現的 Javascript 代碼大多都遵循 2009 年制定的 EACMScript 5 標准,也就是 ES5 標准。現在最新的 Javascript 標准的是 ES6 或者稱為 ES2015。我會用到一些 ES6 的語法,並指出這是 ES6 的特性,這樣讀者就能知道這段 Javascript 代碼遵循的標准。不過讀者並不需要了解 ES6,我也不會對用到的 ES6 特性進行解釋。
運行 Lua
官方安裝指南傳送門。
如果在 Mac 上安裝了 homebrew,運行 brew install lua
。ubuntu 的話,運行 sudo apt-get install lua5.2
,如果從源碼編譯安裝可以安裝最新的版本的 Lua。在 windows 上請使用 LuaDist 安裝。
在 Max OSX 和 Linux 上通過編譯源碼的方式安裝 Lua 很簡單,執行下面的 shell 命令。如果是 Max OS X,把最后一行的 linux 替換為 macosx 。
curl -R -O http://www.lua.org/ftp/lua-5.3.3.tar.gz
tar zxf lua-5.3.3.tar.gz
cd lua-5.3.3 make linux test # Mac 的話把 linux 替換為 macosx.
安裝完成后,就可以使用 lua 命令了,運行 lua 應該看到以下輸出。
$ lua
Lua 5.3.3 Copyright (C) 1994-2016 Lua.org, PUC-Rio >
任意一個文本編輯器都能用來寫 Lua 腳本,寫一段代碼保存為 my_file.lua,執行 Lua 腳本類似 node.js 執行 Javascript 腳本,使用命令就好了。
lua my_file.lua
注釋,空格和分號
Lua 中的多行注釋的以 --[[
開始,以 ]]
結尾。 如果 --
之后沒有 [[
,那么這行是一個單行注釋。例如:
print('Why, hello!') -- print 方法輸出一段字符串 --[[ 這里是一個 多行注釋!]]
Lua 會忽略縮進。一般的空格也會被忽略,但是會保留字符串的空格和單行注釋后面的空白行。行尾的分號可寫可不寫,一般而言不用寫。
變量和作用域
和 Javascript 一樣, Lua 的變量是動態類型的,也使用垃圾回收器管理內存。多數的 Lua 變量類型都能在 Javascript 中找對應的類型。
Javascript 變量類型 | Lua 變量類型 | Lua 變量例子 |
---|---|---|
boolean | boolean | true or false |
null or undefined | nil | nil |
number | number | 3.141 |
string | string | 'hi' or "there" |
object or array | table | {a=1, [2]=false} |
function | function | function() return 42 end |
symbol(ES6) | unique tables | 'hi' or "there" |
It's handy to classify boolean values in term of falsiness; a value is called falsy when it evaluates to false to a boolean context; Lua 中僅有的假值是 nil 和 false。類似地在 Javascript 中,0
,''
和 undefined
都是假值。
Lua 的 numbers
類型,由於歷史原因,使用了浮點數來表示——就像 Javascript 的 numbers
。從 Lua 5.3 開始,Lua 增加了對整數類型的支持,increasing the range of integral values that can be represented exactly.
直觀的來看,如果 Lua 的 number
類型變量被初始化為整數,它被當作一個整數,並且會一直保留整數形式直到遇到可將它變為非整數的操作,比如除法。下面的代碼展示了 Lua 如何處計算數學表達式——有些運算得到整數,有些得到浮點數。
-- Lua
n = 100
print(n) --> 100; 使用整數形式存儲 print(n * 2) --> 200; 運算結果是整數 print(n / 2) --> 50.0; 運算結果是浮點數
類似 Javascript 中的 objects
,Lua 的 table
類型是一個全能的數據結構。
table
可以被用做哈希表或者是數組。不過 Javascript 中 object
的 keys 只能是字符類型,Lua table
的 keys 可以是任何的非 nil
值。在 Lua 中 只有兩個 table 是同一個對象時才會相等,而不是它們擁有相同的內容。
-- Lua
myTable = {}
print(myTable == myTable) --> true print(myTable == {}) --> false
Lua 中 function 是一等公民——可以創建匿名函數,把函數賦值給變量,也可以把函數當作另一個函數的參數或者返回值。如果在函數中引用了定義在該函數作用域之外的自由變量,將隱式地形成一個閉包(譯者注:和 Javascript 中的閉包很類似)。同時 Lua 中的函數支持高效的尾遞歸,也就是在函數的結尾調用另一個函數,調用棧不會增加。
Lua 中還有兩個類型 userdata 和 thread。userdata 是使用 Lua 的 C 語言 API 調用 C 語言生成的對象。userdata 就像一個擁有私有數據的 table,也可以自定義它的行為。 Lua 的 thread 是一個 coroutine,允許函數使用 yield 一些值並保持自身的棧和內部狀態。
作用域和可變性
Lua 中變量的作用域默認是全局作用域。Lua 的 local
關鍵字有點像 Javascript 中的 var
,只不過 Lua 中沒有聲明提升。也就是說,Lua 中的 local
和 ES6 中的 let
一樣,都是塊級作用域。
-- Lua
phi = 1.618034 -- `phi` 是全局變量。 local gamma = 0.577216 -- `gamma` 只在當前的塊作用域下可見。
Lua 中沒有常量或者私有變量。不過可以像 Javascript 中一樣,使用閉包來模擬私有變量。創建一個函數,在函數中引用定義在函數之外的變量,這就使得這些變量在函數之外不可見,達到類似私有變量的效果。 Lua 的函數相關內容將在下一篇文章中涉及。
操作符和表達式
Lua 和 Javascript 中的數學運算,像是加法和乘法,基本上是一樣的。兩者都提供了獲取余數的操作%
,不同的是: Javascript 中的 %
在左側操作數是負數時會返回負值,而 Lua 中的 %
總是返回非負值。Lua 中可以使用 ^ 進行指數操作。
-- Lua
print(2 ^ 10) --> 1024.0 print(-2 % 7) --> 5
Javascript 不支持操作符重載,但是 Lua 支持。Lua 通過一種稱為 metamethods(修改元數據) 特殊函數實現的重載,這部分內容將會在最后一篇文章中解釋。Javascript 有一個三元操作符,但 Lua 中並沒有,不過在 Lua 中能實現類似的效果,這需要借助 Lua 中的短路操作符 or 和 and。
-- Lua
-- Lua 中模擬三元操作符.
local x = myBoolean and valueOnTrue or valueOnFalse -- 例子:找到 a 和 b 的中的最大值. local maxNum = (a > b) and a or b -- 類似 Javascript 中的以下代碼 -- var maxNum = (a > b) ? a : b;
這個實現很有效除非 valueOnTrue 是假值。大部分情況下都不會有問題因為 Lua 的數字,字符和表不會被當作假值。
比較
在 Javascript 中被廣泛認同的的一個最佳實踐是使用 ==
而不是 ==
,因為 Javascript 中的 ==
引發令人疑惑的隱式的類型轉換。對於 ===
, Javascript 只有當比較的值有相同的類型的時候才會返回 true
。
Lua 只有 ==
一種比較操作符,和 Javascript 中的 ===
一樣要求類型相同。以下的例子使用了 Lua 中的內置函數 tonumber
,它將一個字符串轉化為數字。
-- Lua
print(6.0 * 7.0 == '42') --> false, 不同的類型 print(6.0 * 7.0 == tonumber('42')) --> true, 都是 number 類型
Lua 的 <
和 >
操作符在比較的值是不同的類型時將會得到 false
。它們比較字符使用字符標排序,比較數字使用數字排序。
位操作符
Lua 5.3 引入了內置的位操作符,見下表。表中的操作符在 Lua 和 Javascript 中都可用。
操作符 | 含義 |
---|---|
& | 與 |
Ι | 或 |
~ | 取反 |
<< | 左移 |
Lua 中的~
,就像 Javascript 中的 ^。
-- Lua
print(6 & 18) --> 2; 00110b AND 10010b = 00010b. print(6 | 18) --> 22; 00110b OR 10010b = 10110b. print(6 ~ 18) --> 20; 00110b XOR 10010b = 10100b.
Javascript 中區分了 >> 和 >>> 操作符, >> 保持符號而 >>> 使用 0 填充。Lua 中的 >> 就像 Javascript 中的 >>> 的操作符,使用 0 來填充空位。
這篇文章包含了一下基礎知識,運行 Lua並理解 Lua 中的數據類型和表達式。下一篇文章將會包含更多的內容,比如Lua 的流程控制關鍵字,函數和很重要的 table。
微信搜索【水勺子】關注我,獲取更多詳細信息