学习 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。
微信搜索【水勺子】关注我,获取更多详细信息
