`
univasity
  • 浏览: 811576 次
  • 性别: Icon_minigender_1
  • 来自: 广州
社区版块
存档分类
最新评论

[LUA]《Programming in Lua》学习摘录

阅读更多

** 仅仅摘录自《Programming in Lua》,这里只是1-8章的摘录,希望了解更多的请阅读原文。

 

== 第一章 起步

- Chunks -
Chunk 是一系列语句,Lua 执行的每一块语句,比如一个文件或者交互模式下的每
一行都是一个Chunk。

**********************************
每个语句结尾的分号(;)是可选的
**********************************

 

- 全局变量 -
全局变量不需要声明,给一个变量赋值后即创建了这个全局变量,默认初始值为nil。

将变量赋值为nil,即删除一个变量。

 

- 词法约定 -
lua的保留字:
and  break  do  else  elseif
end  false  for  function  if
in  local  nil  not  or
repeat  return  then  true  until
while

Lua 是大小写敏感的.

单行注释:--

多行注释:--[[ --]]

- 命令行方式 -
lua [options] [script [args]]
-e:直接将命令传入Lua
-l:加载一个文件.
-i:进入交互模式.

prompt> lua -e "print(math.sin(12))" --> -0.53657291800043

**************************************************************************
 在运行以前,Lua 使用所有参数构造arg 表。脚本名索引为0,脚本的参数从1 开始
 增加。脚本前面的参数从-1 开始减少。
**************************************************************************


== 第二章 类型和值

Lua 是动态类型语言,变量不要类型定义。

Lua 中有8 个基本类型分别为:nil、boolean、number、string、userdata、function、thread 和table。

变量没有预定义的类型,每一个变量都可能包含任一种类型的值。

***********************************************************************
函数type 可以测试给定变量或者值,print(type("Hello world")) --> string
***********************************************************************

 

- Nil -
Lua 中特殊的类型,他只有一个值:nil;
一个全局变量没有被赋值以前默认值为nil;
给全局变量负nil 可以删除该变量。

 

- Boolean -
两个取值false 和true。

Lua 中所有的值都可以作为条件:
在控制结构的条件中除了false 和nil 为假,其他值都为真。所以Lua 认为0 和空串都是真。

 

- Number -
表示实数,Lua 中没有整数。

 

- String -
指字符的序列。

lua 是8 位字节,可以包含任何数值字符,包括嵌入的0。

Lua 中字符串是不可以修改的,你可以创建一个新的变量存放你要的字符串

****************************************************
 string 和其他对象一样,Lua 自动进行内存分配和释放
 可以使用单引号或者双引号表示字符串
****************************************************

..在Lua 中是字符串连接符(当在一个数字后面写..时,必须加上空格以防止被解释错)。

运行时,Lua 会自动在string 和numbers 之间自动进行类型转换,当一个字符串使
用算术操作符时,string 就会被转成数字。print("10" + 1) --> 11

可以使用[[...]]表示字符串。这种形式的字符串可以包含多行,也可以嵌套且不会
解释转义序列,如果第一个字符是换行符会被自动忽略掉。

*****************************
 字符串转数字:tonumber(args)
 数字转字符串:tostring(args)
*****************************

 

- Function -
函数是第一类值(和其他变量相同),意味着函数可以存储在变量中,可以作为函数
的参数,也可以作为函数的返回值。

 

- Userdata and thread -
userdata 可以将C 数据存放在Lua 变量中,userdata 在Lua 中除了赋值和相等比较外没有预定义的操作。
thread ?

 

- Table -


== 第三章 表达式

Lua 中的表达式包括数字常量、字符串常量、变量、一元和二元运算符、函数调用。
还可以是非传统的函数定义和表构造。

 

- 基本运算符 -
优先级从高到低:
^
not  - (unary)
*  /
+  -
..
<  >  <=  >=  ~=  ==
and
or

******************************************************************
* and 和or 的运算结果不是true 和false,而是和它的两个操作数相关:                                *
* a and b -- 如果a 为false,则返回a,否则返回b                                                            *
* a or b  -- 如果a 为true,则返回a,否则返回b                                                               *
******************************************************************

 

- 表的构造 -
构造器是创建和初始化表的表达式。最简单的构造函数是{},用来创建一个空表。

*************************************************
 第一个元素索引为1
 元素间必须以','或';'划分
 每次调用构造函数,Lua 都会创建一个新的table
*************************************************

/\构造函数可以使用任何表达式初始化:
 tab = {sin(1), sin(2), sin(3), sin(4), sin(5), sin(6), sin(7), sin(8)}

/\初始化一个表作为record 使用可以这样:
 a = {x=0, y=0}  <-->  a = {}; a.x=0; a.y=0

/\使用table 构造一个list:
 list = nil
 for line in io.lines() do
   list = {next=list, value=line}
 end
 这段代码从标准输入读进每行,然后反序形成链表。

我们可以用[expression]显式地表示将被初始化的索引:
opnames = {["+"] = "add", ["-"] = "sub",
           ["*"] = "mul", ["/"] = "div"}
print(opnames["-"]) --> sub
**************************************************************************
 [expression]可以是除了nil的任意类型
 重复定义一个[expression],其值将以最后一个为准list = {[1]=123, [1]=321}
**************************************************************************

 

== 第四章 基本语法
Lua 像C 和PASCAL 几乎支持所有的传统语句:
赋值语句、控制结构语句、函数调用等,同时也支持非传统的多变量赋值、局部变量声明。

 

- 赋值语句 -
Lua 可以对多个变量同时赋值,变量列表和值列表的各个元素用逗号分开,赋值语
句右边的值会依次赋给左边的变量。a, b = 10, 2*x <--> a=10; b=2*x

/\可以这样进行交换变量的值:
             x, y = y, x -- swap 'x' for 'y'
 a[i], a[j] = a[j], a[i] -- swap 'a[i]' for 'a[j]'

当变量个数和值的个数不一致时:
 变量个数>值的个数 -> 按变量个数补足nil
 变量个数<值的个数 -> 多余的值会被忽略

*********************************************************
 遇到赋值语句Lua 会先计算右边所有的值然后再执行赋值操作
 多值赋值经常用来交换变量,或将函数调用返回给变量
*********************************************************

 

- 局部变量与代码块(block)-
使用local 创建一个局部变量,与全局变量不同,局部变量只在被声明的那个代码块内有效。
[代码块:指一个控制结构内,一个函数体,或者一个chunk(变量被声明的那个文件或者文本串)]。

当你想更好的控制局部变量的作用范围的时候可以用do..end划定block的界限(相当于C/C++的{..}块)。

*********************************
* 应该尽可能的使用局部变量,有两个好处:    *
* 1. 避免命名冲突                                       *
* 2. 访问局部变量的速度比全局变量更快.        *
*********************************

 

- 控制结构语句 -
控制结构的条件表达式结果可以是任何值,Lua 认为false 和nil 为假,其他值为真。

<if 语句>
01、
if conditions then
  //then-part
end;

 

02、
if conditions then
  //then-part
else
  //else-part
end;

 

03、
if conditions then
  //then-part
elseif conditions then
  //elseif-part
..   --->多个elseif
else
  //else-part
end;

 

<while 语句>
while condition do
  //statements;
end;

 

<repeat-until 语句>
repeat
  //statements;
until conditions;

 

<for 语句>

01.数值for循环
for var=exp1,exp2,exp3 do
  //loop-part
end
***********************************************************************
for 将用exp3 作为step 从exp1(初始值)到exp2(终止值),执行loop-part。
其中exp3 可以省略,默认step=1

有几点需要注意:                                            
1. 三个表达式只会被计算一次,并且是在循环开始前。           
2. 控制变量var 是局部变量自动被声明,并且只在循环内有效。     
3. 循环过程中不要改变控制变量的值,那样做的结果是不可预知的。
   如果要退出循环,使用break 语句。     
***********************************************************************

 

02.范型for 循环
-- print all values of array 'a'
for i,v in ipairs(a) do
    print(v)
end
****************************************
i不可手动赋值,默认从1开始递增
v为a[i]的值
如果a的索引为非默认的,该元素将被忽略掉
list = {['a']=a, b, c} --> b,c
****************************************

-- print all keys of table 't'
for k in pairs(t) do
    print(k)
end
********************************************
k不可手动赋值,默认从1开始递增
如果a的索引为非默认的,该元素将最后依次列出
list = {['a']=a, b, c, ['b']=d} --> 2,3,1,4
********************************************

范型for 和数值for 有两点相同:
1. 控制变量是局部变量
2. 不要修改控制变量的值

 

- break 和return 语句 -
break 语句用来退出当前循环(for、repeat、while)。在循环外部不可以使用。
return 用来从函数返回结果,当一个函数自然结束时,结尾会有一个默认的return。

Lua 语法要求break 和return 只能出现在block 的结尾一句。
**************************************************************************
有时候为了调试或者其他目的需要在block 的中间使用return 或者break,可以显式
的使用do..end 来实:
function foo ()
  return   --<< SYNTAX ERROR
  -- 'return' is the last statement in the next block
  do return end -- OK
  ...   -- statements not reached
end
**************************************************************************


== 第五章 函数
函数有两种用途:
1.完成指定的任务,这种情况下函数作为调用语句使用;
2.计算并返回值,这种情况下函数作为赋值语句的表达式使用。

function func_name (arguments-list)
  //statements-list;
end;
*********************************************************************
1.调用函数的时候,如果参数列表为空,必须使用()表明是函数调用。
2.当函数只有一个参数并且这个参数是字符串或者表构造的时候,()可有可无:
  print "Hello World" <--> print("Hello World")
  print [[a multi-line <--> print([[a multi-line
             message]]                 message]])
3.函数的参数可以被省略,默认值为Nil:
  function f(t, i)
      i = i or 0;
      return t+i;
  end
  print(f(1)); --> 1
*********************************************************************

 

- 多返回值 -
Lua 函数可以返回多个结果值,比如string.find,其返回匹配串“开始和结束的下标”
(如果不存在匹配串返回nil)。

*************************************
可以使用圆括号()强制使调用返回一个值。
*************************************

函数多值返回的特殊函数unpack,接受一个数组作为输入参数,返回数组的所有元素。

 

- 可变参数 -
Lua 函数可以接受可变数目的参数,和C 语言类似在函数参数列表中使用三点(...)
表示函数有可变的参数。Lua 将函数的参数放在一个叫arg 的表中,除了参数以外,arg
表中还有一个域n 表示参数的个数:
function g (a, b, ...) end
 CALL             PARAMETERS
 g(3)              a=3, b=nil, arg={n=0}
 g(3, 4)          a=3, b=4, arg={n=0}
 g(3, 4, 5, 8)  a=3, b=4, arg={5, 8; n=2}
Lua 会将前面的实参传给函数的固定参数,后面的实参放在arg 表中。

 

- 命名参数 -
Lua 的函数参数是和位置相关的,调用时实参会按顺序依次传给形参。

w = Window {
  x=0, y=0, width=300, height=200,
  title = "Lua", background="blue",
  border = true
}

function Window (options)
  -- check mandatory options
  if type(options.title) ~= "string" then
    error("no title")
  elseif type(options.width) ~= "number" then
    error("no width")
  elseif type(options.height) ~= "number" then
    error("no height")
  end
 
  -- everything else is optional
  _Window(options.title,
    options.x or 0, -- default value
    options.y or 0, -- default value
    options.width, options.height,
    options.background or "white", -- default
    options.border -- default is false (nil)
  )
end


== 第六章 再论函数
Lua 中的函数是带有词法定界(lexical scoping)的第一类值(first-class values)。
*****************************************************************************
第一类值指:在Lua 中函数和其他值(数值、字符串)一样,函数可以被存放在变量中,
            也可以存放在表中,可以作为函数的参数,还可以作为函数的返回值。
词法定界指:嵌套的函数可以访问他外部函数中的变量。
*****************************************************************************

 

Lua 中函数也可以没有名字,匿名的。
函数名实际上是一个指向函数的变量,和其他变量是一样的。
*******************************************
function foo (x) return 2*x end
这实际上是Lua 语法的特例,下面是原本的函数:
foo = function (x) return 2*x end
*******************************************

 

以其他函数作为参数的函数在Lua 中被称作高级函数(higher-order function)。
在Lua 中,高级函数与普通函数没有区别,它们只是把“作为参数的函数”当作第一类值(first-class value)处理而已。
**************************************************************************
table 标准库提供一个排序函数,接受一个表作为输入参数并且排序表中的元素:
  table.sort(network, function (a,b) return (a.name > b.name) end)
**************************************************************************

 

- 闭包 -
当一个函数内部嵌套另一个函数定义时,内部的函数体可以访问外部的函数的局部
变量,这种特征我们称作词法定界。
%% 具体内容较复杂,请自行查看原文 %%

 

- 非全局函数 -

 

- 正确的尾调用(Proper Tail Calls) -
当函数最后一个动作是调用另外一个函数时,我们称这种调用尾调用。
尾调用之后程序不需要在栈中保留关于调用者的任何信息,递归的层次可以无限制的。


== 第七章 迭代器与泛型for

- 泛型for的语义 -
在循环过程中泛型for 在自己内部保存迭代函数,实际上它保存三个值:
 迭代函数、状态常量、控制变量

文法:
for <var-list> in <exp-list> do
  <body>
end
***********************************************
<var-list>是以一个或多个逗号分隔的变量名列表,
<exp-list>是以一个或多个逗号分隔的表达式列表,
通常情况下exp-list 只有一个值:迭代工厂的调用。
***********************************************

 

在很多情况下变量列表也只有一个变量
我们称变量列表中第一个变量为控制变量,其值为nil 时循环结束。

for var_1, ..., var_n in explist do block end
等价于
do
  local _f, _s, _var = explist
  while true do
    local var_1, ... , var_n = _f(_s, _var)
    _var = var_1
    if _var == nil then break end
    block
  end
end

 

- 无状态的迭代器 -
无状态的迭代器是指不保留任何状态的迭代器
无状态迭代器的典型的简单的例子是ipairs,他遍历数组的每一个元素。

迭代的状态包括被遍历的表(循环过程中不会改变的状态常量)和当前的索引下标
(控制变量),ipairs 和迭代函数都很简单,我们在Lua 中可以这样实现:
function iter (a, i)
  i = i + 1
  local v = a[i]
  if v then
      return i, v
  end
end

 

function ipairs (a)
   return iter, a, 0
end

*****************************************************************************
我们应该尽可能的写无状态的迭代器,因为这样循环的时候由for 来保存状态,不
需要创建对象,花费的代价小;如果不能用无状态的迭代器实现,应尽可能使用闭包;尽
可能不要使用table 这种方式,因为创建闭包的代价要比创建table 小,另外Lua 处理闭
包要比处理table 速度快些。
******************************************************************************

 

- 真正的迭代器 -

function allwords (f)
    -- repeat for each line in the file
    for l in io.lines() do
        -- repeat for each word in the line
        for w in string.gfind(l, "%w+") do
            -- call the function
            f(w)
        end
    end
end


== 第八章 编译·运行·错误信息
虽然我们把Lua 当作解释型语言,但是Lua 会首先把代码预编译成中间码然后再执行。

dofile 编译并执行代码,如果发生错误会抛出错误信,每次执行都要重新编译
loadfile 编译但不执行代码,如果发生错误会返回错误代码,只需要编译一次便可多次运行
dostring 与dofile相似,从一个串中读入
loadstring 与loadfile相似,从一个串中读入

*****************************************
function dofile (filename)
  local f = assert(loadfile(filename))
  return f()
end
*****************************************

loadfile 和loadstring 都不会有边界效应产生,他们仅仅编译chunk 成为自己内部实现的一个匿名函数。
通常对他们的误解是他们定义了函数。Lua 中的函数定义是发生在运行时的赋值而不是发生在编译时。

 

- require 函数 -
Lua 提供高级的require 函数来加载运行库。

粗略的说require 和dofile 完成同样的功能但有两点不同:
1. require 会搜索目录加载文件
2. require 会判断是否文件已经加载避免重复加载同一文件。

由于上述特征,require在Lua 中是加载库的更好的函数。

 

- 错误处理 -
你也可以通过调用error函数显式地抛出错误,error的参数是要抛出的错误信息。
print "enter a number:"
n = io.read("*number")
if not n then error("invalid input") end

Lua提供了专门的内置函数assert来完成上面类似的功能:
print "enter a number:"
n = assert(io.read("*number"), "invalid input")

assert首先检查第一个参数,若没问题,assert不做任何事情;否则,assert以第二个参数作为错误信息抛出。第二个参数是可选的。注意,assert会首先处理两个参数,然后才调用函数,所以下面代码,无论n是否为数字,字符串连接操作总会执行:
n = io.read()
assert(tonumber(n), "invalid input: " .. n .. " is not a number")

当函数遇到异常有两个基本的动作:返回错误代码或者抛出错误。选择哪一种方式,没有固定的规则,不过基本的原则是:对于程序逻辑上能够避免的异常,以抛出错误的方式处理之,否则返回错误代码。

 

如果在Lua中需要处理错误,需要使用pcall函数封装你的代码。
pcall在保护模式(protected mode)下执行函数内容,同时捕获所有的异常和错误。若一切正常,pcall返回true以及“被执行函数”的返回值;否则返回nil和错误信息。

 

第十章例举了两个完整的例子... 其他章节在继续学习中...^-^

最后附上《Programming In Lua》的word版:

 

分享到:
评论

相关推荐

    Beginning Lua Programming电子书

    《Beginning Lua Programming》是一本适合初学者入门的优秀教材,不仅覆盖了Lua语言的基础知识,还深入讲解了进阶和高级主题。无论是对于想要快速了解Lua语言的读者,还是希望进一步提升自己编程技能的专业人士,...

    Lua Programming Gems 英文版 pdf,高清

    这本书以英文版呈现,具有高清的阅读体验,适合广大对Lua编程有热情的开发者学习。 Lua是一种轻量级、动态类型的脚本语言,其设计目标是简洁、可嵌入和高效。在《Lua Programming Gems》中,作者们探讨了Lua的高级...

    Programming in Lua(中文版).pdf

    《Programming in Lua》是一本专为学习和精通Lua编程语言而编写的权威指南。这本书的中文版提供了对Lua语言深入且全面的解析,适合初学者和有经验的程序员使用。Lua是一种轻量级、高性能、易扩展的脚本语言,广泛...

    Programming in Lua Fourth edition

    《Programming in Lua Fourth Edition》是关于Lua编程语言的一本权威指南,由Luiz Henrique de Figueiredo、Ricardo Tomasi和Tiago Fonseca共同撰写。这本书详细介绍了Lua语言的核心概念、语法和特性,是学习和精通...

    Lua Programming Gems 高清

    通过学习《Lua Programming Gems》,读者可以深入了解如何利用这些特性进行高效编程。 其次,书中的章节涵盖了Lua的函数、模块、对象和类。Lua支持基于原型的面向对象编程,允许开发者通过表来创建和操作对象。此外...

    LUA编程programminginlua.rar

    这个压缩包"LUA编程programminginlua.rar"包含了学习LUA编程的重要资源。 打开"Programming in Lua.pdf",你可以找到对LUA语言全面而详细的讲解。这本书首先介绍了LUA的基础,如变量、数据类型(包括数字、字符串、...

    Lua5.1全三套:Lua Programming(中英文版)+中文手册

    总的来说,"Lua5.1全三套:Lua Programming(中英文版)+中文手册"是一套全面的Lua学习资料,无论你是初学者还是经验丰富的开发者,都能从中获益。通过学习这些材料,你可以掌握Lua的基本语法,理解其核心概念,进而...

    Programming in Lua(4th) 无水印pdf

    Programming in Lua(4th) 英文无水印pdf 第4版 pdf所有页面使用FoxitReader和PDF-XChangeViewer测试都可以打开 本资源转载自网络,如有侵权,请联系上传者或csdn删除 本资源转载自网络,如有侵权,请联系上传...

    Programming In Lua

    Programming in Lua provides a solid base to any programmer who wants to use Lua. It covers all aspects of Lua—from the basics to its API with C. The book is the main source of programming patterns ...

    programming in lua_lua_

    在《Programming in Lua》中,你可以学习到以下关键知识点: 1. **基础语法**:包括变量、数据类型(如数字、字符串、布尔、表、函数和nil)、操作符、控制结构(如条件语句和循环)以及错误处理。 2. **表与元表*...

    Programming In Lua 中文版PDF高清

    - **简述**:介绍了《Programming in Lua》这本书的目的、适用对象以及为何选择Lua作为学习对象等内容。 - **知识点**:了解Lua语言的特点及其应用场景。 **第1章 起点** - **简述**:讲解了如何安装Lua环境,以及...

    Programming in Lua(2nd Edition)

    《Programming in Lua》第二版是一本介绍Lua编程语言的经典著作,由Roberto Ierusalimschy撰写,是深入了解和学习Lua语言的宝贵资源。Lua是一种轻量级的、高效、易于嵌入的脚本语言,广泛应用于游戏、移动应用、网络...

Global site tag (gtag.js) - Google Analytics