您的位置:首页 > 编程语言 > Lua

Lua学习笔记(2)-语句、函数

2017-05-31 11:05 501 查看
这块主要记录Lua语句的写法

Lua中除了基本的赋值、控制结构、过程调用语句外,还有一些特殊用法如多重赋值(multiple assignment)和局部变量声明

赋值语句

多重赋值语句用法:

> a,b=10,20
> print(a)
10
> print(b)
20
>


在多重赋值语句中,Lua会先将等号右边所有元素都求值完然后依次对左边赋值,并且右边多出来的将会被丢弃。若右边值少于左边变量,则左边多余的变量会被赋nil

如下语句是将x,y值交换:

x , y = y , x


多重赋值的意义:

用于变量交换

接受函数多个返回值时,如a,b=fun(),fun()将返回两个值,a接收第一个,b接收第二个

局部变量和块(block)

局部变量的定义 local i=1,作用于一个语句块即一个控制结构内或一个函数内。需要注意的是,交互模式即命令行下本身每一行就是一个语句块,上一行定义的local变量可能到下一行就失效了。可通过do end来指定变量的作用域,如下do end包起来的部分就是a2的作用域.

> do
>> local a2=123
>>
>> print(a2)
>> end
123
>


Lua的控制结构

关键字作用
if以end结尾
while, repeat, for用于循环,while和for以end结尾,repeat以until作为结尾
if语句学习:

--if语句

print("\n\n if语句测试: input a please:")

str=io.read()
a=tonumber(str)

if( a == nil) then
print(str.." is not number")
elseif(a<0) then
print("input less than 0")
elseif (a==0) then
print("input is 0")
else
print("input more than 0")
end


while语句:

--while study

a={12,31221,"fdafdf","fdf","43424",true,false}
local i=1
while(a[i]) do
print( a[i])
i=i+1
end


repeat语句用法:

--但打印输入的第一行不为空的内容

print("输入字符串并换行,#为终止")
repeat
line = io.read()
until line == "#"

print(line)


for语句demo:

--[[for循环语句,
数字型的结构

for var exp1,exp2,exp3 do
<执行体>
end

其中exp1为起点,exp2为变化终点,exp3为步长

--需要注意:
1.是exp123是在开始前一次性求值的。
2.var 限定了有效周期只在if语句内,
因此如果end之后还想拿var的值,只能在循环中把var存到别的变量中去!
--]]

for i = 1, 100, 6 do
print(i)
end

--[[
泛型的for(generic for),通过迭代器来遍历所有值,

Lua标准库提供的迭代器:
1.迭代文件中每行的io.lines
2.迭代table元素的pairs
3.迭代数组元素的ipairs
4.迭代字符串中单词的 string.getmatch

--]]

print("\n\n\n泛型的for测试:")

a={"fdfsd","dsd",1232,true}
for i,v in ipairs(a) do
print(v)
end

break和 return 语句

--[[
for 语句的一个用法,逆向table.

--]]
days={"Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"}
revdays={}
for k,v in pairs(days) do
revdays[v]=k
end
print("revdays=")
print(revdays)

print("days['Sunday']=",days["Sunday"])
print("revdays['Sunday']=",revdays["Sunday"])


break和return语句:

书中说:

break and return 必须是一个块的最后一条语句,或是end,else,until前的一条语句?

并且举例直接写一个空函数如下:

function foo()
return


说是语法错误,空return或break需要用do end 包起来。

但是我在自己的解释器尝试了下,直接写空语句是正常的。

这部分主要记录Lua的函数语句相关

普通函数

在Lua中,语句的特点:

- 函数语句提供多种写法

以print()函数为例:

-- print() fucntion

a=123
print(a) -- normal print

print "ffdfdfd" -- when print one string or table

print [[fasdfasffdf
fdghfdgf
ghfhghg]]       --when print multiline string


Lua中函数实参的个数可以跟形参不同,Lua会根据实际情况决定补默认参数 还是丢弃多余参数

传参demo:

-- about function parameters

function testFun( a, b) return  a or b end

print( testFun(12,32))
print( testFun(12,"lisi",3232))
print( testFun( ))
print( testFun( "sdf"))


Lua函数可以有多个返回值的特性,结合多重赋值语句来用。

如下demo函数有两个返回值并使用:

--function multiple results

s,e = string.find("hello lua user", "us")

print("find res=",s,e)


并且,当多重赋值语句的右边多个参数中包含参数调用的时候:

如果右边的函数调用不是再最后一个位置,则赋值时,只会取用函数的第一个返回值给左边赋值。

如下的执行结果,z,m都为nil了

> x,y,z,m=string.find("hello lua user", "us"),"zhangaaa"
> print(x,y,z,m)
11      zhangaaa        nil     nil


==但是, 如果函数作为右边最后一个参数,会将函数所有返回值依次赋值给左边,==

除非左边的变量不够导致结果丢弃。比如语句,则x,y,z都会有值,m会被填为nil

> x,y,z,m="zhang",string.find("hello lua user", "us")
> print(x,y,z,m)
'zhang'
11
12
>


但是如果想要避免Lua取多个函数返回值给左赋值呢?可以在调函数的时候加括号,限定它只返回一个结果:

> x,y,z,m="zhang", (string.find("hello lua user", "us"))
> print(x,y,z,m)
'zhang'
11
>


此外,圆括号除了在赋值情境中,普通函数return中也具有截取第一个值的效果,如下demo:

-- () special use
function getname(a) return a,"a girl" end

function getname_2(a)
return getname(a)  --return a all results
end

function getname_3(a)
return (getname(a))  --return a first results
end


运行结果,会发现print(getname_3(“aabb”)) 只有一个返回值了。

> print(getname(12))
12
'a girl'
> print(getname_2("aa"))
'aa'
'a girl'
> print(getname_3("aabb"))
'aabb'
>


特殊函数unpack函数,可实现变长参数的传递。unpack函数会接受一个数组。

--系统函数 unpack,实现动态的传递参数,实现任意函数的调用
--like f(unpack(a))
f= string.find
a={"hello world","worl"}

> print( f(unpack(a)))
7
10
>


变长参数(variable number of arguments)

如下实现一个边长参数的求和:

--定义一个边长的函数?
function add(...)
local s=0;
for i, v in ipairs{...}do
s = s + v
end
return s
end

> print(add(1,2,3,4,45,5,5))
65
>


小demo,如下格式化显示函数,长的特别像C语言的打印函数,注io.write()函数的打印结果是不带换行的

--格式化文本 string.format和输出文本 io.write函数
function fwrite(fmt,...)
return io.write(string.format(fmt,...))
end

> fwrite("%d%s",23,"zhang san")
23zhang san>


具名实参用法(named arguments),即像C#中的传参时通过paramName:value的形式指定传那个参数的值。

但是在Lua中是默认不支持具名实参的,即便是在系统函数的使用中,因此,想要实现具名实参的效果 只能自己“包装一下”,或者在自定义函数中去实现这个效果。

以系统函数os.rename()文件重命名为例,调用方法只能是:

os.rename("e:/project/mystudy/luastudynew/test_3.lua","e:/project/mystudy/luastudynew/test_4.lua")


但是可以添加一个自定义函数去实现具名实参的效果,基本思想是将函数参数改造为table,talbe就有key value的属性了。但是会发现,调用方法也会有不同,原先是圆括号()的格式,改造后变成了rename{}的格式,

function rename(arg)
return os.rename(arg.old,arg.new)
end

--调用
> rename{old="e:/project/mystudy/luastudynew/test_3.lua",new="e:/project/mystudy/luastudynew/test_4.lua"}


尽管如此看起来比较别扭,但在遇到超长系统函数时。改造一下还是值得的

深入函数

既然单拆出一个章节,应该是概念有别于普通函数,在Lua中,函数属于“第一类值”(First-Class Value),即跟数字、字符串等的操作方法都相同。函数的调用也相当于一个表达式。

如下这两个函数的声明方法,第二个方法更直接解释了,函数的声明就相当于定义了一个返回类型为函数的表达式啊

> function foo(x) return 2*x end
> print(foo(3))
6
> foo=function(x) return 2*x end
> print(foo(3))
6
>


闭合函数(closure)的概念

词法域的概念:

若将一个函数写在另一个函数内,则这个位于函数内部的函数便可以访问外部函数中的局部变量。

小贴士:由于在Lua中函数可以保存到变量中,这个特性可以实现函数的重定义,甚至是重定系统函数。

用途:可以限定使用 被重新实现的函数。

如下demo重定义了系统函数math.sin(),在装载该文件前后,执行math.sin的效果是不同的,默认sin()的参数是作为一个弧度的,但重定义之后的函数sin()参数会作为一个角度来使用。

--实现系统函数 math.sin()的重定义,以后调用math.sin()都相当于调用这个函数了。
do
local oldSin = math.sin;   --将老的系统函数保存在了局部变量中。
local k = math.pi/180

math.sin=function(x)
return oldSin(x*k)
end
end

> print(math.sin(12))
-0.53657291800043

> dofile "e:/project/mystudy/luastudynew/function_demo.lua"

> print(math.sin(12))
0.20791169081776
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  lua 函数