學習 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。
微信搜索【水勺子】關注我,獲取更多詳細信息

