《Lua程序设计》之 补充知识

八、补充知识

8.1 局部变量和代码块

对于局部代码块的声明,如

local i = 1

这个在交互模式中不能正常读到i的值。因为在交互模式中,每一行代码就是一个代码段(除非不是一条完整的命令),要想解决这个问题,可以用do-end,如

> do
>> local i = 1
>> print(i+1)
>> end
2
> 

do-end还可以用于需要更好的控制某些局部变量的生效范围时,如

local a,b,c = 1,2,1
local x1,x2
do 
    local a2=2*a
    local d = (b^2 - 4*a*c)^(1/2)
    x1=(-b+d)/a2
    x2=(-b-d)/a2
end
print(x1,x2)

尽可能的使用局部变量是一种良好的编程风格。

Lua语言有一种常见的用法

local foo = foo

将全局变量foo赋值给声明的局部变量foo,这个用法的好处在于

  1. 在需要提高对全局变量foo的访问速度时
  2. 当其他函数改变了全局变量foo的值,而代码段又需要保留foo的原始值时

8.2 控制结构

控制结构的条件表达式的结果可以是任何值。请记住,Lua语言将所有不是false和nil的值当做真,特别的,Lua语言将0和空字符串也当做真

8.2.1 if then end

由于Lua语言不支持switch语句,所以一下的if-elseif-then-end语句比较常见

if op == "+" then
    r = a+b
elseif op == "-" then
    r = a-b
elseif op == "*" then
    r = a*b 
elseif op == "/" then
    r = a/b
else
    error('Invalid operation')
end 
8.2.2 while

都好简单,就看个语法吧

local i = 1
while a[i] do
    print(a[i])
    i = i+1
end
8.2.3 repeat

repeat-until的特殊之处在于,至少会执行一次,而且在Lua语言中,循环体内声明的局部变量的作用域包括测试条件:

--使用Newton-Raphson法计算'x'的平方根
x = 100
local sqr = x/2
repeat
    sqr = (sqr+x/sqr)/2
    local error = math.abs(sqr^2 - x)
    print(error)
until error < x/10000       --局部变量'error'此时仍然可见
8.2.3 数值型for和泛型for

数值型for

for var = exp1,exp2,exp3 do   --exp1初始值,exp2是最大值,exp3是步长
    something
end

for i = 1,10,2 do   --i是局部变量
    print(i)
end
print(i)            --i打印的是空值

for j = 1,math.huge do  --用math.huge就是循环没上限,默认步长是1
    print(j)
end

泛型for

for i,v in ipairs(table_name) do  --i和v也都是局部变量
    print(i,v)
end

for k,v in pairs(table_name) do
    print(k,v)
end

for cmd_list in io.lines(file_path) do
    print(cmd_list)
end

8.2 break、return和goto

所有函数的最后都有一个隐藏的return,所以我们不需要在每一个没有返还值的函数最后书写return语句。

goto是Lua 5.2添加进去的;goto后面紧跟标签名,标签名可以是任意有效的标志符,标签的语法 ::name::

在使用goto语句跳转时,Lua语言设置了一些限制条件:

  1. 标签遵循常见的可见性规则,因此不能直接跳转到一个代码块中的标签
  2. goto不能跳转到函数外
  3. goto不能跳转到局部变量的作用域

比如,Lua语言没有的continue、redo和局部错误处理等,用goto都可以实现,如下:

while some_condition do
    ::redo::
    if some_other_condition then 
        goto continue
    elseif yet_another_condition then 
        goto redo
    end
    some code
    ::continue::
end

Lua语言规范中一个很有用的细节是,局部变量的作用域终止于声明变量的代码块中的最后一个有效(non-void)语句处,标签被认为是无效(void)语句,看下列代码:

while some_condition do
    if some_other_condition then 
        goto continue
    end
    local var = something
    some code
    ::continue::
end

var的作用域终止于some code

我这边玩了下io.read()函数

> do
>> x = io.read(1)
>> print('haha' ..x)
>> end
juudei
hahaj

用goto写一个状态机

::s1:: do
    local c = io.read(1)
    if c == '0' then goto s2
    elseif c == nil then print 'ok'; return
    else goto s1
    end
end

::s2:: do
    local c = io.read(1)
    if c == '0' then goto s1
    elseif c == nil then print 'not ok'; return
    else goto s2
    end
end

goto s1

推荐阅读更多精彩内容

  • Nginx 的配置文件使用的就是一门微型的编程语言,许多真实世界里的 Nginx 配置文件其实就是一个一个的小程序...
    SkTj阅读 2,842评论 0 7
  • 注:lua5.0以上版本去除了table.getn方法,可以用#tableName代替 函数有两种用途:1.完成指...
    _小圆球_阅读 249评论 0 0
  • 函数有两种用途: 完成指定任务,此时函数作为调用语句使用。 计算并返回值,此时函数作为赋值语句的表达式使用。 调用...
    JunChow520阅读 1,985评论 0 3
  • 大多数 Nginx 新手都会频繁遇到这样一个困惑,那就是当同一个location配置块使用了多个 Nginx 模块...
    SkTj阅读 5,219评论 0 12
  • 第一篇 语言 第0章 序言 Lua仅让你用少量的代码解决关键问题。 Lua所提供的机制是C不擅长的:高级语言,动态...
    testfor阅读 1,616评论 1 7