Lua 函数用法和它的"诡异"之处

Lua 函数调用时, 需要带括号(对于单个参数的函数,某些值不需要用括号, 如字符串, 表). 

但是注意return是可以带括号也可以不带括号的.

这里重点说到括号, 因为括号和返回多值的函数关系很大, 也就是"诡异"的地方, 后面会举例.

函数可以作为一个语句执行, 那有点类似一个过程语言, 执行完的函数结果被抛弃掉.

例如 : 

print("abc") -- 这作为一个语句执行.

函数也可以在一个表达式中执行, 那么结果会被返回, 对于多值函数需要注意返回的值的个数.

例如 :

i = math.sin(123)  -- 这里的math.sin函数在表达式中, 所以结果返回.

函数调用必须带括号, 除了单个参数的函数, 并且参数类型为字符串, 表构造器时, 可以不带括号.

例如:

> print {1,2,3}
table: 0x9465c0
> print [====[
>> hellp
>> nihao
>> ]]
>> ]====]
hellp
nihao
]]
> print "hello"
hello
> print {}
table: 0x946d10

函数的结构

包含函数名, 参数, 函数体几个部分.

例如 :

function add(a)
  local sum = 0
  for i = 1, #a do
    sum = sum + a[i]
  end
  return sum
end

函数的参数, 和本地变量类似, 调用函数时为值传递的方式. 在函数中修改这个变量对传入的变量没有影响. 

同时, 函数调用时允许传入的参数个数和函数定义的个数不一致的情况.

例如

function f (a,b)
  print(a,b)
end

可以这么调用 : 

> function f(a,b)
>>   print(a,b)
>> end
> f()  -- a,b都为nil
nil     nil
> f(1)  -- a=1, b=nil
1       nil
> f(2)
2       nil
> f(1,2,3)  -- a=1, b=2, 3抛弃
1       2
> f(1,2)
1       2

如果函数参数缺失的情况下, 可以给它默认值, 我现在还不清楚是不是可以在函数定义时指定, 如果不能的话就这么这么搞了.

function f(a,b)
  if a == nil then a = 1 end
  if b == nil then b = 1 end
  print(a,b)
end

为什么不用 a= a or 1呢? 因为当传入的是boolean值时, false的话, false or 1也变1了.

这个是Lua的一种逻辑判断值的取值问题. 例如

a or b  -- 当a = nil或false时, a or b这个逻辑判断表达式的值就是b, 当a不为false或者nil时, 那么这个表达式的值就是a.
> print(false or 1)
1
> print(0 or false)
0
> print(0 or "hello")
0
> print(nil or "hello")
hello
> print(false or "hello")
hello

a and b 则当a为真(不为false或nil)时, 表达式的结果等于b, 如果a为真, 则表达式的结果为a.

> print(1 and false)
false
> print(1 and nil)
nil
> print(1 and 2)
2
> print(false and "hello")
false
> print(nil and "hello")
nil

Lua支持一个函数返回多个值, 但是返回多个值时, 有多少个值传递, 或者被抛弃, 和用法有关, 比较诡异的地方来了.

> print(string.find("hello","llo"))
3       5
string.find("hello","llo")函数返回2个值, 第一个值为匹配到的字符串的开始位置, 第二个值为结束位置.

但是, 当多值函数后面再有表达式时, 多值函数就只返回第一个值, 后面的值被抛弃.

> print(string.find("hello","llo"), "hell")  -- 这样的话string.find("hello","llo")只返回了第一个结果3. 5被抛弃了.
3       hell

在赋值时也一样

> a,b = string.find("hello","llo")
> print(a,b)
3       5
> a,b = string.find("hello","llo"), "he"
> print(a,b)
3       he

还有一种情况, 如果要强制使用仅仅返回1个结果的话, 在函数外加括号就可以. 这就是文章开头提到的括号用法.

> a=(string.find("hello","llo"))
> print(a)
3
> a=string.find("hello","llo")
> print(a)
3
> print(string.find("hello","llo"))
3       5
> print((string.find("hello","llo")))  -- 多值函数用括号包一层, 返回第一个结果值. 而不是整个list
3

多值函数例子 : 

> function max(a)
  local mi = 1 -- index
  local m = a[mi]
  for i=1,#a do
    if a[i] > m then
      mi = i; m = a[i]
    end
  end
  return m, mi
end
> print(max({1,2,3,4,5}))
5       5
> print(max({1,2,3,4,5,100}))
100     6

比较容易记住Lua的多值返回函数的诡异的例子 : 

> function foo0() end
> function foo1() return "a" end
> function foo2() return "a", "b" end
> x,y = foo2()
> print(x,y)
a       b
> x = foo2()
> print(x)
a
> x,y,z = 10,foo2()   -- 在这里, 也要注意, 后面有值的情况下, 多值函数都只取一个值. 没有值的话, 全取.
> print(x,y,z)
10      a       b
> x,y = foo0()
> print(x,y)
nil     nil
> x,y = foo1()
> print(x,y)
a       nil
> x,y,z = foo2()
> print(x,y,z)
a       b       nil
> x,y = foo2(), "hello"   -- 在这里, 也要注意, 后面有值的情况下, 多值函数都只取一个值.
> print(x,y)
a       hello
> x,y = foo0(), "hello", "nihao"
> print(x,y)
nil     hello
> t = {foo0(), foo2(), 4}  -- 在这里, 也要注意, 后面有值的情况下, 多值函数都只取一个值.
> print(t)
table: 0x9515c0
> for i = 1,#t do
>> print(t[i])
>> i = i+1
>> end
nil
a
4
> t = {foo0(), foo2()}
> for i = 1,#t do
print(t[i])
i = i+1
end
nil
a
b
> print(foo2(),1)   -- 在这里, 也要注意, 后面有值的情况下, 多值函数都只取一个值.
a       1
> print(foo2())
a       b
时间: 2025-01-07 18:47:03

Lua 函数用法和它的"诡异"之处的相关文章

lua 函数参数传递问题

问题描述 lua 函数参数传递问题 function test(t) t1 = t table.insert(t1,10) end t = {1,2,3,4} test(t) for k, v in pairs(t) do print (v) end 为何t插入了10? 解决方案 lua中通过值比较Boolean,String,Number类型的值,而通过引用比较Table,function,userdate类型的值. ?????????????? a = {}; a.x = 1; a.y =

C语言中调用Lua函数实例_Lua

记得上学时,初中英文课本中,上网叫做surfing the internet,中文叫网上冲浪.那个时期,人们经常称互联网为赛博空间.如今工作了,大量的零碎时间用于上微博,知乎,QQ,这些碎片化的阅读让人读起来轻松,也能获取些粗浅的信息.然而它们是消耗时间的黑洞,时间就这样一分一秒地飞逝,年末的时候,知乎会告诉你回答了多少问题,阅读了相当于一部<红楼梦>那么多的文字.只是当你静下来一想,这些浅阅读并没给你带来有深度,系统的知识.在你的时间线上,两条相邻信息往往是八竿子也打不着的.而且你还时不时去

C语言模块回调Lua函数的两种方法_Lua

lua和C通过虚拟栈这种交互方式简单而又可靠,缺点就是C做栈平衡稍微会多写一点代码. 今天分享学到的C模块回调Lua函数的两种方法,都是炒冷饭,大侠勿喷. 1. C保存函数对象 C模块可以通过注册表保存Lua里面的对象,等适当时候取出再调用即可. 复制代码 代码如下: static int lua_callback = LUA_REFNIL; static int setnotify(lua_State *L) {   lua_callback = luaL_ref(L, LUA_REGISTR

把Lua函数传递到C/C++中实例_Lua

问题 在Lua中,因为函数也是第一类值,所以会出现将函数作为另一个函数的参数,或者函数作 为函数的返回值.这种机制在很多地方都能代码更灵活更简洁,例如: 复制代码 代码如下: table.sort(table [,comp]) 这里的comp就要求传入一个函数,我们在调用时,大概会有如下形式: 复制代码 代码如下: table.sort(t, comp) -- 直接写函数名     table.sort(t, local_comp) -- 某个局部函数     table.sort(t, fun

Lua编程示例(六): C语言调用Lua函数_Lua

C++端: #include "stdafx.h" lua_State *L; void load_lua(lua_State **L,char *filename){ *L=luaL_newstate(); luaL_openlibs(*L); if(luaL_loadfile(*L,filename) || lua_pcall(*L,0,0,0)){ luaL_error(*L,"load file error! %s",lua_tostring(*L,-1))

Lua函数用法研究_Lua

在Lua 基本语法快速入门 中有涉及到函数的用法,但只是普通的应用,并没有深成次的研究一下,介于函数用的还是比较多的就专门做个专题研究一下~   一.函数.变量的用法 函数的定义用关键字function .然后加函数名和变量.注意后面没有do.最后以end结束. 在函数中的变量默认是全局变量,但通常情况下函数中的变量都是在函数中有效的.所以要在声明的时候加上"local" 标明只在局部有效.二.返回多个结果值 在Lua中的函数可以返回多个返回值.这与C等语言有很大的不同.因为从根本上讲

Lua 函数--函数

        在Lua中,函数是一种对语句和表达式进行抽象的主要机制.函数既可以完成某项特定的任务,也可以只做一些计算并返回结果.         Lua具有一项非常于总不同的特征,允许函数返回多个结果: s, e = string.find("Hello Lua users", "Lua") print(s, e)            -->7    9         以Lua编写的函数同样可以返回多个结果,只需在return关键字后列出所有返回值即可

C++中调用Lua函数实例_Lua

唉,今天心情有点糟糕,我就少说一些啰嗦的话了. (旁白:太好了-) 上一章传送门:http://www.jb51.net/article/55096.htm 经过前面几章的介绍,相信大家对Lua的堆栈已经比较熟悉了,如果还不是很熟悉的朋友,建议多看几遍前面的教程,或者多敲几次代码. 那么,如果已经对Lua的堆栈比较熟悉,接下来的内容就很简单了. 今天我们来看看C++如何调用Lua的函数,先看看现在Lua文件是什么样的: 复制代码 代码如下: -- helloLua.lua文件 myName =

Lua函数与字符串处理简明总结_Lua

函数的定义是以function关键字开始的,后面函数的名称,然后是要传递给函数的参数,如果没有参数传给函数,仍然需要用()来表示一个空的参数列表,以end关键字结尾. 复制代码 代码如下: function 函数名()  ...  ...  ... end 1. 单一参数 复制代码 代码如下: function F_1(var)  print("My website is: "  var) end 参数var传递给了函数,并在函数中使用,同时,函数中的参数是局部变量,在函数调用结束后被