【在主画面加入捷径】
       
【选择语系】
繁中 简中

[书籍回顾] Programming in Lua, 4th edition 评价

REVIEW

    前言

    Lua 算是一个相对小众的语言,通常会学 Lua 的程序人都有某种明确的目的,比较不会把 Lua 当成通用型语言来学。常见的使用方式是搭配游戏引擎来写电脑游戏,像是 Corona 或 Defold 等;或是写游戏的外挂,像是魔兽世界 (World of Warcraft);或者是把 Lua 内嵌到宿主软件中。

    Lua 在 5.1、5.2、5.3 版之间有一些不兼容的变动,在撰写 Lua 程序或阅读 Lua 数据时需注意。本书的 Lua 目标版本是 5.3 版,如果要写旧版本的 Lua 程序,仍然可参考本书,只是要小幅修改一部分程序。

    由于本书的作者是 Lua 的爸爸 Roberto Ierusalimschy,本书相当有指针性,可视为 Lua 的圣经。此外,购买本书时同时在赞助 Lua 的永续发展。

    本书共 310 页,分为 33 章,介于轻量级和中量级之间;但本书字偏多,没办法很快读完。本书分为四部,前三部讲 Lua,最后一部讲 Lua C API,如果用不到 C 的部分,最后一部可以略过不读。接下来,我们会逐一介绍各个章节。

    I. The Basics

    本部讲解 Lua 基础语法元件。

    1. Getting Started

    本书谈到如何撰写 Lua 程序,分为互动模式 (interactive mode) 和批次模式 (batch mode),实务上都会写好 Lua 脚本后再执行,互动模式仅是用来练习语法。接着讲解识别字 (identifier)、类型 (types)、注解 (comments) 等基本概念。

    2. Interlude: The Eight-Queen Puzzle

    本章展示如何用 Lua 解经典的八皇后问题,有空可以欣赏一下。

    3. Numbers

    本章讲述 Lua 的数字体别。Lua 5.3 版引入整数,和先前的版本有一些差异,在撰写程序时需注意。此外,本章说明数字运算相关的运算符、数学函式库、产生乱数等议题。

    4. Strings

    本章讲述 Lua 的字串类型。原本 Lua 的字串是 byte 序列,没有针对特定的编码来储存;但 Lua 在 5.3 版引入一个处理 UTF8 字串的函式库。此外,也讲到字串相关的运算符及字串函式库。

    5. Tables

    表 (tables) 是 Lua 唯一的数据结构,由于表在 Lua 中相当实用,可做为数组 (array)、关连式数组 (associative array)、物件 (object) 等,学习表的使用相当重要。本章学习表的基本用法,不会触及面向对象程序的部分。

    6. Functions

    本章讲解基本的函式写法,其他较进阶的写法就留在后续章节中。

    7. The External World

    本章讲解 Lua 的基本输出入,像是文件的读取或写入、调用外部命令、读取环境变量等。

    8. Filling Some Gaps

    本章讲解一些未归类的语法特性:

    • 局部变量 (local variables)
    • 区块 (blocks)
    • 控制结构 (control structures)

    因这些内容篇幅偏短,故集中到同一章节来介绍。

    II. Real Programming

    本部讲解一些相对进阶的 Lua 语法。

    9. Closures

    本章带入一些基本的函数式程序的概念,像是函式物件 (function object) 等。Lua 其实也支援一些函数式程序的特性,本章算是暖身,为之后讲解函数式程序做准备。

    10. Pattern Matching

    正规表示式 (regular expression) 引擎所占的程序代码量较大,若要在 Lua 这类轻薄短小的语言中塞入整个正规表示式引擎,整个语言的空间量会过大,不符内嵌语言的设计目标。因此,Lua 引入 pattern matching 做为替代的方案,本章讲解 pattern matching 的语法和使用方式。

    11. Interlude: Most Frequent Words

    承续上一章,本章展示如何用 Lua 计算文字出现频率,有空可以欣赏一下。

    12. Date and Time

    本章讲述 Lua 如何处理日期 (date) 和时间 (time) 这两个在程序中重要的概念,主要是透过 os.dateos.time 这两个函式库来处理。

    13. Bits and Bytes

    本章讲述二进位运算及二进位文件的处理。

    14. Data Structures

    由于 Lua 只有表 (table) 这个数据结构,本章讲述如何用表仿真其他的数据结构,包括数组 (array)、矩阵 (matrix)、串行 (linked list)、队列 (queue)、集合 (set)、图 (graph) 等。本章内容算蛮实用的,有需要的读者可以阅读一下。

    15. Data Files and Serialization

    本章探讨数据序列化的议题。一般来说,XML 或 JSON 是常见的数据序列化格式;但 Lua 本身其实也可以做为一种数据描述语言,虽然通用性不若 JSON 来得好,但在 Lua 程序中更加方便。本章展示数个数据序列化的手法;由于数据序列化没有制式的方法,会随需求而变,需耐心阅读本章,从中找出适合自己的方案。

    16. Compilation, Execution, and Errors

    本章讲解几个和 Lua 运作相关的概念:

    • 动态载入
    • 预先编译的位元码 (bytecode)
    • 错误处理

    虽然不会这些内容还是可以写 Lua 程序,了解一下对撰写 Lua 程序会有一些概念。

    17. Modules and Packages

    当程序变大后,把全部程序写在同一个脚本会不易管理;此外,把程序以模块拆开也利于重覆使用。本文介绍 Lua 模块的使用和撰写,算是重要的章节,可以花时间阅读。

    III. Lua-ism

    本部仍在讲解 Lua 语法,但属于较进阶的部分。笔者个人以为,除了面向对象程序比较重要外,其他的部分就尽量学习即可,如果不习惯这些特性,不使用仍可撰写 Lua 程序。

    18. Iterators and the Generic for

    本章讲述撰写迭代器 (iterators) 的方法以及如何用 for 来走访迭代器。本章较偏函数式程序设计,如果不习惯这种程序的写法,可以用其他写法来代替。

    19. Interlude: Markov Chain Algorithom

    本章展示如何以 Lua 实现马可夫链,这个算法相对较难,如果用不到的话,欣赏一下即可。

    20. Metatables and Metamethods

    Metatable 是 Lua 中用来实现面向对象程序的机制,而 metamethods 则是 Lua 中实现运算符重载的机制,两者都算是重要的概念。原作者特别把这些内容独立在一章中,为面向对象程序进行暖身。

    21. Object-oriented Programming

    沿续上一章的内容,本章讲述面向对象程序的写法。Lua 的物件算是轻量级的,没有实现所有的面向对象特性,在写物件时需注意。这两章应该是这一部中最重要的章节,需仔细阅读。

    22. The Environment

    本章说明 Lua 处理全局变量的机制。重点在于利用 _ENV 变量减少命令空间的污染;另外,应尽量减少全局变量的使用。对于中大型程序来说,全局变量会变成重要的议题。

    23. Garbage

    本章讲述如何在 Lua 中控制垃圾回收相关的议题。一开始写程序时不会立即用到这个部分,但程序碰到瓶颈时,可以回头看一看这个部分,看能不能对程序做出一些改善措施。

    24. Coroutines

    Coroutine 类似于线程 (thread),不过 coroutine 只能单线程运作,这是和线程最大的差异。在 Lua 中 coroutine 有数个用途,像是写迭代器、写事件导向程序、写协同性多工程序等。Coroutine 算是比较进阶的概念,一开始无法立即掌握也无妨。

    25. Reflection

    透过 Lua 的 reflection,我们可以把程序当成数据处理,例如,利用 debug.getinfo函数来得到函式的元数据 (metadata)。Reflection 多用于调试 (debugging) 和效能分析 (profiling),我们平常不会用到 reflection 相关的功能。此外,reflection 相关功能可能会拖累程序效能。如果一开始觉得陌生也无妨,因为不会很常用到。

    26. Interlude: Multithreading with Coroutines

    本章展示如何用 coroutine 写多线程程序,本章的特点在于利用网络下载的等待时间执行下一段程序,藉以达成有限度的多线程程序。这个范例算比较进阶的用法,一开始无法掌握也无妨。

    IV. The C API

    本部讲解如何在 C 程序中嵌入 Lua,如果没有要在宿主软件中嵌入 Lua 的话,这部可以略过不看。

    由于 Lua 在不同版本间的 C API 有一些不兼容,一开始时就要选择好 Lua 的版本。有些程序人会偏好 LuaJIT 这个非官方的 Lua 实现品,因 LuaJIT 比起 Lua 有更好的效能 (参考这里),LuaJIT 约略介于 Lua 5.1 和 5.2 版之间。本书的 Lua 目标版本是 5.3,如果要使用别的版本,仍然可以透过本部来学 Lua C API,但要查阅一下其他版本的 API 手册。

    27. An Overview of the C API

    本章讲述 Lua C API 的基本写法,重点在于操作 Lua 状态机。Lua 状态机以栈为基础,Lua 程序的数据都储存在这个状态机中,不会给宿主 C 程序带来额外的全局变量。本章算是蹲马步,看完本章还没办法直接用这套 API 写应用程序。

    28. Extending Your Application

    本章用三个情境来说明如何以 Lua 扩展 C 程序的功能:

    • 读取常数
    • 读取表 (tables)
    • 读取函式 (functions)

    透过这些手法,之后我们只要透过修改该 Lua 脚本就可以更动应用程序的功能,不需重新编译整个应用程序。

    29. Calling C from Lua

    在本章中,我们学习如何以 C 撰写 Lua函数,透过这些手法,我们可以扩展 Lua 程序的行为。这章刚好和上一章相反,我们在宿主软件中撰写函式来扩展 Lua 程序的行为,达到原本 Lua 标准函式库没有的行为。

    30. Techniques for Writing C Functions

    本章沿续前一章,讲述一些用于撰写函式的辅助 API,针对以下情境:

    • 操作数组
    • 操作字串
    • 储存函式的状态

    31. User-Defined Types in C

    本章学习如何用 C 撰写 Lua 自定义类型,也就是在 Lua 程序中的 user data。由于自定义类型可以用面向对象的方式来使用,比起函式是更高一阶的扩展。

    32. Managing Resources

    在本章中,我们撰写可控制外部资源的宿主程序,再将这些程序包装成 Lua 可用的函式或物件。一些实例像是开启数据夹或解析 XML 文件等。

    33. Threads and States

    本章探讨如何在 Lua C API 层级撰写多线程程序。这里有两种意义,一种是 coroutine,一种是系统级的多线程程序;前者以 Lua C API 即可完成,后者则需依赖系统上的多线程函式库。本章提供一个以 POSIX Threads 实现的多线程程序。

    结语

    虽然 300 多页乍看不是很多,本书的文字相当扎实,细细阅读得花上一些时间。本书注重原理讲解,大部分程序代码范例偏短且不是完整的程序,而是程序代码片段。欧美的程序设计书籍多用这种风格来写,好处是易抓到重点,但要自己去花时间写范例程序,以确认自己所学和书上的知识相符。

    如何购买

    透过以下链接即可购买本书。

    TAGS: LUA