https://www.oreilly.com/learning/learn-lua-from-javascript-part-1-an-introduction-to-lua
learn lua from javascript, part 1: An introduction to Lua
學習 Lua 對于了解 Javascript 的人來說就是小菜一碟,Tyler Neylon 寫了三篇文章來解釋其中的原因,這是其中的第一篇。
這是通過 Javascript 來學習 Lua 系列文章的第一篇,一共有三篇,第二篇和第三篇。
登陸 Tyler 的免費的網(wǎng)絡廣播頻道收聽 Lua 能做什么?
Lua 是一門優(yōu)雅的,可移植的,高效的并且異常靈活的語言。所有能夠編譯 C 語言的操作系統(tǒng)都能運行 Lua,這是一些跨平臺的框架,比如 Corona SDK 和 Love game engine,選擇 Lua 的原因。Lua 的運行速度很快,足夠用來開發(fā)游戲——憤怒的小鳥的最初是用 Lua 編寫的。 Lua 能和其他的語言很好的融合在一起,它作為腳本語言,在 Adobe lightroom 項目中有出色的表現(xiàn)。我認為 Lua 的設計很優(yōu)美,用起來也非常的舒服。
對于已經(jīng)了解 Javascript 的人而言,學習 Lua 是非常簡單的,因為Lua 和 Javascript 有很多的共同點。在學習的過程中,我們可以通過這些共同點很快的熟悉 Lua,但需要注意兩者間一些關鍵性的不同的地方。
通過 Javascript 的相關知識學習 Lua 的系列總共三篇,這是其中的第一篇。這篇文章中包含一些基礎概念:安裝 Lua,變量,數(shù)據(jù)類型,操作符和表達式。第二篇將會涉及流程控制和數(shù)據(jù)結構,第三篇講解對象相關的一些知識。
文章中出現(xiàn)的 Javascript 代碼大多都遵循 2009 年制定的 EACMScript 5 標準,也就是 ES5 標準。現(xiàn)在最新的 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 很簡單,執(zhí)行下面的 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,執(zhí)行 Lua 腳本類似 node.js 執(zhí)行 Javascript 腳本,使用命令就好了。
lua my_file.lua
注釋,空格和分號
Lua 中的多行注釋的以 --[[
開始,以 ]]
結尾。 如果 --
之后沒有 [[
,那么這行是一個單行注釋。例如:
print('Why, hello!') -- print 方法輸出一段字符串
--[[ 這里是一個
多行注釋!]]
Lua 會忽略縮進。一般的空格也會被忽略,但是會保留字符串的空格和單行注釋后面的空白行。行尾的分號可寫可不寫,一般而言不用寫。
變量和作用域
和 Javascript 一樣, Lua 的變量是動態(tài)類型的,也使用垃圾回收器管理內存。多數(shù)的 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
類型,由于歷史原因,使用了浮點數(shù)來表示——就像 Javascript 的 numbers
。從 Lua 5.3 開始,Lua 增加了對整數(shù)類型的支持,increasing the range of integral values that can be represented exactly.
直觀的來看,如果 Lua 的 number
類型變量被初始化為整數(shù),它被當作一個整數(shù),并且會一直保留整數(shù)形式直到遇到可將它變?yōu)榉钦麛?shù)的操作,比如除法。下面的代碼展示了 Lua 如何處計算數(shù)學表達式——有些運算得到整數(shù),有些得到浮點數(shù)。
-- Lua
n = 100
print(n) --> 100; 使用整數(shù)形式存儲
print(n * 2) --> 200; 運算結果是整數(shù)
print(n / 2) --> 50.0; 運算結果是浮點數(shù)
類似 Javascript 中的 objects
,Lua 的 table
類型是一個全能的數(shù)據(jù)結構。
table
可以被用做哈希表或者是數(shù)組。不過 Javascript 中 object
的 keys 只能是字符類型,Lua table
的 keys 可以是任何的非 nil
值。在 Lua 中 只有兩個 table 是同一個對象時才會相等,而不是它們擁有相同的內容。
-- Lua
myTable = {}
print(myTable == myTable) --> true
print(myTable == {}) --> false
Lua 中 function 是一等公民——可以創(chuàng)建匿名函數(shù),把函數(shù)賦值給變量,也可以把函數(shù)當作另一個函數(shù)的參數(shù)或者返回值。如果在函數(shù)中引用了定義在該函數(shù)作用域之外的自由變量,將隱式地形成一個閉包(譯者注:和 Javascript 中的閉包很類似)。同時 Lua 中的函數(shù)支持高效的尾遞歸,也就是在函數(shù)的結尾調用另一個函數(shù),調用棧不會增加。
Lua 中還有兩個類型 userdata 和 thread。userdata 是使用 Lua 的 C 語言 API 調用 C 語言生成的對象。userdata 就像一個擁有私有數(shù)據(jù)的 table,也可以自定義它的行為。 Lua 的 thread 是一個 coroutine,允許函數(shù)使用 yield 一些值并保持自身的棧和內部狀態(tài)。
作用域和可變性
Lua 中變量的作用域默認是全局作用域。Lua 的 local
關鍵字有點像 Javascript 中的 var
,只不過 Lua 中沒有聲明提升。也就是說,Lua 中的 local
和 ES6 中的 let
一樣,都是塊級作用域。
-- Lua
phi = 1.618034 -- `phi` 是全局變量。
local gamma = 0.577216 -- `gamma` 只在當前的塊作用域下可見。
Lua 中沒有常量或者私有變量。不過可以像 Javascript 中一樣,使用閉包來模擬私有變量。創(chuàng)建一個函數(shù),在函數(shù)中引用定義在函數(shù)之外的變量,這就使得這些變量在函數(shù)之外不可見,達到類似私有變量的效果。 Lua 的函數(shù)相關內容將在下一篇文章中涉及。
操作符和表達式
Lua 和 Javascript 中的數(shù)學運算,像是加法和乘法,基本上是一樣的。兩者都提供了獲取余數(shù)的操作%
,不同的是: Javascript 中的 %
在左側操作數(shù)是負數(shù)時會返回負值,而 Lua 中的 %
總是返回非負值。Lua 中可以使用 ^ 進行指數(shù)操作。
-- Lua
print(2 ^ 10) --> 1024.0
print(-2 % 7) --> 5
Javascript 不支持操作符重載,但是 Lua 支持。Lua 通過一種稱為 metamethods(修改元數(shù)據(jù)) 特殊函數(shù)實現(xiàn)的重載,這部分內容將會在最后一篇文章中解釋。Javascript 有一個三元操作符,但 Lua 中并沒有,不過在 Lua 中能實現(xiàn)類似的效果,這需要借助 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;
這個實現(xiàn)很有效除非 valueOnTrue 是假值。大部分情況下都不會有問題因為 Lua 的數(shù)字,字符和表不會被當作假值。
比較
在 Javascript 中被廣泛認同的的一個最佳實踐是使用 ==
而不是 ==
,因為 Javascript 中的 ==
引發(fā)令人疑惑的隱式的類型轉換。對于 ===
, Javascript 只有當比較的值有相同的類型的時候才會返回 true
。
Lua 只有 ==
一種比較操作符,和 Javascript 中的 ===
一樣要求類型相同。以下的例子使用了 Lua 中的內置函數(shù) tonumber
,它將一個字符串轉化為數(shù)字。
-- Lua
print(6.0 * 7.0 == '42') --> false, 不同的類型
print(6.0 * 7.0 == tonumber('42')) --> true, 都是 number 類型
Lua 的 <
和 >
操作符在比較的值是不同的類型時將會得到 false
。它們比較字符使用字符標排序,比較數(shù)字使用數(shù)字排序。
位操作符
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 中區(qū)分了 >> 和 >>> 操作符, >> 保持符號而 >>> 使用 0 填充。Lua 中的 >> 就像 Javascript 中的 >>> 的操作符,使用 0 來填充空位。
這篇文章包含了一下基礎知識,運行 Lua并理解 Lua 中的數(shù)據(jù)類型和表達式。下一篇文章將會包含更多的內容,比如Lua 的流程控制關鍵字,函數(shù)和很重要的 table。