Chinaunix首页 | 论坛 | 博客
  • 博客访问: 684000
  • 博文数量: 132
  • 博客积分: 10060
  • 博客等级: 上将
  • 技术积分: 1732
  • 用 户 组: 普通用户
  • 注册时间: 2007-12-21 12:35
个人简介

迷惘的码农。

文章分类

全部博文(132)

文章存档

2013年(1)

2011年(2)

2010年(9)

2009年(41)

2008年(79)

我的朋友

分类: Java

2008-08-15 11:08:14

2.4 -

Lua支持语句的常规集,类似于Pascal或C。该集包括赋值、控制结构、函数调用和变量声明。

2.4.1 -

Lua的执行单元(unit)称为单元(chunk)。一个单元只是一系列的语句,它们被顺序执行。每条语句可随意地以一个分号结束:

	chunk ::= {stat [`;´]}

不允许空语句,因而‘;;’不合法。

Lua将单元视为带不定参数的匿名函数进行处理(见)。正因如此,单元可定义局部变量、接收参数以及返回值。

单元可以存储在一个文件中或者存在于宿主程序的一个字符串中。当单元被执行时,首先它被预编译为虚拟机中的指令,然后编译后的代码被虚拟机的解释器执行。

但愿也可被预编译为二进制形式;细节参考程序luac。源码中的程序和编译后的形式可交换的;Lua自动检测文件类型进而作相应地处理。

2.4.2 -

语句块(block)是一系列语句;从语法上讲,语句块同单元一样:

	block ::= chunk

语句块可被显式地分隔以产生单条语句:

	stat ::= do block end

显式的语句块有助于控制变量声明的作用预。有时显式的语句块也用于在另一个语句块中加入returnbreak语句(见)。

2.4.3 -

Lua允许多重赋值。因此,赋值得语法定义为左边一系列变量和右边一系列表达式。两个系列中的元素都用逗号分隔:

	stat ::= varlist `=´ explist
varlist ::= var {`,´ var}
explist ::= exp {`,´ exp}

表达式在中讨论。

赋值以前,值列表被调整匹配变量列表的长度。如果值比需要的多,多出的值被丢弃。如果值比需要的少,就用适当数量的nil扩展值列表。如果表达式列表以一个函数调用结束,那么调整之前该调用所返回的所有值都进入值列表(除非该调用被扩在圆括号中;见)。

赋值语句首先计算它的所有表达式,然后才会执行赋值操作。因此代码

     i = 3
i, a[i] = i+1, 20

设置a[3]为20,而不影响a[4],因为a[i]中的i在它被赋值为4之前被计算(为3)。同样地,代码行

     x, y = y, x

交换xy的值。

向全局变量和表字段赋值的含义可通过元表被改变。向索引的变量t[i] = val赋值等价于settable_event(t,i,val)。(函数settable_event的完整说明见。在Lua中该函数并不存在或不可访问。我们这儿用它只作说明的目的。)

向全局变量x = val赋值等价于赋值_env.x = val,后者又等价于

     settable_event(_env, "x", val)

此处_env是当前运行函数的环境。(在Lua中未定义变量_env。我们这儿用它只作说明的目的。)

2.4.4 -

控制结构ifwhilerepeat具有通常的含义和相似的语法:

	stat ::= while exp do block end
stat ::= repeat block until exp
stat ::= if exp then block {elseif exp then block} [else block] end

Lua也有for语句,它有两种风格(见)。

控制结构的条件表达式可能返回任何值。falsenil都作为假。所有不同于nilfalse的值作为真(特别要注意,数字0和空字符串也是真)。

repeatuntil循环中,内部代码块并非截止于until关键字,而是在条件之后。所以,条件也能引用在循环体中声明的本地变量。

return语句用来从函数或单元(其实也是函数)中返回一些值。 函数和单元可以返回多个值,所以return语句的语法是

	stat ::= return [explist]

break语句用于终止whilerepeatfor循环的执行,跳到循环之后的下一条语句:

	stat ::= break

break终止最内层的循环。

returnbreak语句只能写作代码块的最后一条last语句。如果确实需要在代码块中部returnbreak,可以用do return enddo break end这种方式显式地加入内部代码块,这样returnbreak就是他们的(内部)代码块中的最后一条语句了。

2.4.5 -

for语句有两种形式:数字形式和一般形式。

数字形式的for循环随着控制变量在算术级数(等差级数,arithmetic progression)中移动,重复执行一块代码。语法如下:

	stat ::= for Name `=´ exp `,´ exp [`,´ exp] do block end

name从第一个exp的值开始,直到它以第三个exp为步长通过第二个exp为止,block被重复执行。更确切地说,for语句类似

     for v = e1, e2, e3 do block end

等价于代码:

     do
local var, limit, step = tonumber(e1), tonumber(e2), tonumber(e3)
if not (var and limit and step) then error() end
while (step > 0 and var <= limit) or (step <= 0 and var >= limit) do
local v = var
block
var = var + step
end
end

注意事项如下:

  • 三个控制变量都只在循环开始前计算一次。它们都必须得到数字值。
  • varlimitstep是不可见变量。此处的名字只为方便说明。
  • 如果省略第三个表达式(步长),则步长为1。
  • 你可用break退出for循环。
  • 循环变量v是循环局部的;不能在for结束或被打断之后使用。如果需要该值,可在打断或退出循环之前赋给另一个变量。

一般形式的for语句重复检查称为迭代器(iterator)的函数。每次迭代,调用迭代器函数以产生一个新值,如该值为nil则停止。一般形式的for循环语法如下:

	stat ::= for namelist in explist do block end
namelist ::= Name {`,´ Name}

for语句类似

     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

注意下列事项:

  • explist只计算一次。其结果是一个迭代器函数、一个状态机(state),以及第一个迭代器变量(iterator variable)的初始值。
  • fs,和var是不可见变量。此处的名字只为方便说明。
  • 可用break退出for循环。
  • 循环变量var_i是循环局部的;for结束后不可使用。如果需要它们,在打断或退出循环之前把它们赋给其他的变量。

2.4.6 -

为了允许使用可能的副作用,函数调用可作为语句执行:

	stat ::= functioncall

此时所有的返回值被丢弃。函数调用在中解释。

2.4.7 -

可在代码块内部的任何位置声明局部变量。声明时可赋初值:

	stat ::= local namelist [`=´ explist]

如果存在,赋初值同样有多重赋值的语义(见)。否则,所有变量初始化为nil

单元也是代码块(见),因此可在任何显式的代码块外面声明局部变量。这种局部变量的作用域延伸到单元末尾。

局部变量的可见性规则在中说明。

阅读(1564) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~