Lua学习笔记(2)-语句、函数
2017-05-31 11:05
501 查看
这块主要记录Lua语句的写法
Lua中除了基本的赋值、控制结构、过程调用语句外,还有一些特殊用法如多重赋值(multiple assignment)和局部变量声明
在多重赋值语句中,Lua会先将等号右边所有元素都求值完然后依次对左边赋值,并且右边多出来的将会被丢弃。若右边值少于左边变量,则左边多余的变量会被赋nil
如下语句是将x,y值交换:
多重赋值的意义:
用于变量交换
接受函数多个返回值时,如a,b=fun(),fun()将返回两个值,a接收第一个,b接收第二个
if语句学习:
while语句:
repeat语句用法:
for语句demo:
break和return语句:
书中说:
break and return 必须是一个块的最后一条语句,或是end,else,until前的一条语句?
并且举例直接写一个空函数如下:
说是语法错误,空return或break需要用do end 包起来。
但是我在自己的解释器尝试了下,直接写空语句是正常的。
这部分主要记录Lua的函数语句相关
- 函数语句提供多种写法
以print()函数为例:
Lua中函数实参的个数可以跟形参不同,Lua会根据实际情况决定补默认参数 还是丢弃多余参数
传参demo:
Lua函数可以有多个返回值的特性,结合多重赋值语句来用。
如下demo函数有两个返回值并使用:
并且,当多重赋值语句的右边多个参数中包含参数调用的时候:
如果右边的函数调用不是再最后一个位置,则赋值时,只会取用函数的第一个返回值给左边赋值。
如下的执行结果,z,m都为nil了
==但是, 如果函数作为右边最后一个参数,会将函数所有返回值依次赋值给左边,==
除非左边的变量不够导致结果丢弃。比如语句,则x,y,z都会有值,m会被填为nil
但是如果想要避免Lua取多个函数返回值给左赋值呢?可以在调函数的时候加括号,限定它只返回一个结果:
此外,圆括号除了在赋值情境中,普通函数return中也具有截取第一个值的效果,如下demo:
运行结果,会发现print(getname_3(“aabb”)) 只有一个返回值了。
特殊函数unpack函数,可实现变长参数的传递。unpack函数会接受一个数组。
变长参数(variable number of arguments)
如下实现一个边长参数的求和:
小demo,如下格式化显示函数,长的特别像C语言的打印函数,注io.write()函数的打印结果是不带换行的
具名实参用法(named arguments),即像C#中的传参时通过paramName:value的形式指定传那个参数的值。
但是在Lua中是默认不支持具名实参的,即便是在系统函数的使用中,因此,想要实现具名实参的效果 只能自己“包装一下”,或者在自定义函数中去实现这个效果。
以系统函数os.rename()文件重命名为例,调用方法只能是:
但是可以添加一个自定义函数去实现具名实参的效果,基本思想是将函数参数改造为table,talbe就有key value的属性了。但是会发现,调用方法也会有不同,原先是圆括号()的格式,改造后变成了rename{}的格式,
尽管如此看起来比较别扭,但在遇到超长系统函数时。改造一下还是值得的
如下这两个函数的声明方法,第二个方法更直接解释了,函数的声明就相当于定义了一个返回类型为函数的表达式啊
闭合函数(closure)的概念
词法域的概念:
若将一个函数写在另一个函数内,则这个位于函数内部的函数便可以访问外部函数中的局部变量。
小贴士:由于在Lua中函数可以保存到变量中,这个特性可以实现函数的重定义,甚至是重定系统函数。
用途:可以限定使用 被重新实现的函数。
如下demo重定义了系统函数math.sin(),在装载该文件前后,执行math.sin的效果是不同的,默认sin()的参数是作为一个弧度的,但重定义之后的函数sin()参数会作为一个角度来使用。
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语句 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基础教程之赋值语句、表达式、流程控制、函数学习笔记
- lua学习笔记二--函数
- JavaScript基础学习笔记(二)——操作符、语句、函数
- Lua学习笔记二--在Lua中使用自己的C函数收藏
- Lua学习笔记3. 函数可变参数和运算符、转义字符串、数组
- Lua学习笔记之函数
- lua学习笔记之函数
- C++ Primer 学习笔记12 函数(return语句、函数声明、局部对象、内联函数、类的成员函数、重载函数)
- lua学习笔记---选择,循环语句
- Lua学习笔记--基本语法规则&控制流语句
- Lua学习笔记之表和函数
- Lua 学习笔记(四) —— 函数(一)
- lua学习笔记之再淡for语句的遍历
- 5.lua学习笔记:函数
- Lua中文教程学习笔记 (4) 函数
- Swift_学习笔记_控制语句和函数
- C++ Primer 学习笔记_22_函数(续1) --return语句、递归调用、函数声明
- Lua 学习笔记(四)语句与控制结构
- [LUA学习笔记03]LUA函数和C函数的相互调用
- Lua学习笔记(五):函数