lua函数深入了解

函数是一种“第一类值”,它们具有特定的词法域。

“第一类值”表示在lua中函数域其他传统类型的值句用相同的权利。函数可以存储到变量中(无论是全局变量还是局部变量)或table中,可以作为实参传递给其他函数,也可以作为其他函数的返回值。

“词法域”是值一个函数可以嵌套在另一个函数中,内部的函数可以访问外部函数中的变量。

函数与所有其他值一样都是匿名的,即他们都没有名称。当讨论一个函数名,实际上是在讨论一个持有某函数的变量。这与其他变量持有各种值一个道理,可以以多种方式来操作这些变量。如下例:

local a = {p = print}
a.p("hello world")
print = math.sin 
a.p(print(1))
sin = a.p
sin(10,20)

输出为:

hello world
0.8414709848079
10	20

我们经常这样定义函数

 function foo(x) return 2 * x end

实际上,这只是一种“语法糖”而已;上述代码只是下面代码的一种简化书写形式

foo = function (x) return 2 * x end

实际上,一个函数定义实际就是一条语句(更准确地说是一条赋值语句),这条语句创建了一种类型为“函数”的值,并将这个值赋予一个变量。由于函数在Lua中就是一个普通的值,所以不仅可以将其存储在全局变量中,还可以存储在局部变量甚至table的字段中。

关于函数的语法域,我们看一下下面的例子:

function new()
	local i = 0
	return function()
		i = i+1
		return i
    end
end

local new1 = new()
print(new1())
print(new1())

输出为:

1
2

在上述代码中,有一个变量i,对于函数new来说,i是一个局部变量,但是对于匿名函数来说,当它访问这个i时,i既不是全局变量,也不是局部变量,对于我们来说,我们称这样的变量为一个“非局部的变量”。下面这段代码也是同样的道理:

function new(i)
	return function()
		i = i+1
		return i
    end
end

local new1 = new(10)
print(new1())
print(new1())

输出:

11
12

匿名函数访问了一个“非局部的变量”i,该变量用于保持一个计数器。乍一看,由于创建变量i的函数,也就是new已经返回,所以之后每次调用匿名函数时,i都应该是已经超出了作用范围。但是,Lua会以closure的概念来正确地处理这种情况。一个closure就是一个函数加上该函数所需访问的所有“非局部的变量”。如果再次调用newCounter,那么它会创建一个新的局部变量i,从而将得到一个新的closure。关于闭包,我们接下来会进行讨论。

时间: 2024-10-15 01:02:53

lua函数深入了解的相关文章

C语言调用Lua函数

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

lua函数精讲(一)

函数的用途: 1.完成指定的任务,这种情况下作为调用语句使用. 2.计算并返回值,这种情况下,函数作为赋值语句的表达式使用. 函数的参数为空,必须使用()表示函数调用.例外:当函数只有一个参数,并且这个参数是字符串或表构造时,()是可选的. lua提供了面向对象调用函数的语法 o:foo(x)与o.f(o,x)是等价的. lua函数的实参与形参的匹配与赋值语句类似,多余部分被忽略,缺少部分nil补足. lua函数可以返回多个值,return后列出要返回值的列表即可返回多值 s, e = stri

C中调用Lua函数

我们先来看一个简单的例子: lua_State* L = NULL; // 内部调用lua函数 double f(double x, double y) { double z; lua_getglobal(L, "f"); // 获取lua函数f lua_pushnumber(L, x); // 压入参数x和y lua_pushnumber(L, y); if(lua_pcall(L, 2, 1, 0) != 0) error(L, "error running functi

Lua函数执行流程及函数延续点问题的研究

第一:Lua函数调用的总体流程 在保护性调用的情况下,lua中函数调用的流程如下,非保护性调用的流程更加简单,请追踪lua_call函数 int docall (lua_State *L, int narg, int nres) | —— int lua_pcallk (lua_State *L, int nargs, int nresults, int errfunc ...) | —— luaD_pcall (lua_State *L, Pfunc func, void *u,ptrdiff

lua 函数练习

1 --逻辑表达式 2 3 --1+2+3+...+n 4 function fun1(n) 5 local sum = 0 6 for i=1,n do 7 sum = sum + i 8 end 9 return sum 10 end 11 12 -- 计算奇数和 13 function fun2(n) 14 local sum = 0 15 for i=1,n,2 do 16 sum = sum + i 17 end 18 return sum 19 end 20 21 -- 计算偶数和

cocos2d-x 3.0 在C++中调用lua函数(2)

个人觉得3.0里面, 在C++下面调用lua函数很不方便, 所以就扩展了一个类, 继承自LuaStack, 代码和使用方式如下: #ifndef __CC_LUA_STACKEX_H_ #define __CC_LUA_STACKEX_H_ #include "CCLuaStack.h" NS_CC_BEGIN class LuaStackEx : public LuaStack { public: void call_script_fun(const char* fun) { exe

c++回调lua函数,实现事件

基于上一篇文章 cocos2dx 导出c++类供lua使用 上一篇主要是因为不能调用lua函数 才那样解决,但是本篇能调用lua函数,那么目的实现也就简单多了 归其原因还是tolua 工具生成的hpp cpp文件的函数不对 虽然在c++中函数参数声明为LUA_FUNCTION 但是还是被当做了int处理 所以我们要手动处理函数的调用 也就是修改生成的 函数 ... 生成的对应 代码 改为以下 if (NULL == tolua_S) return 0; int argc = 0; NetMgr*

lua函数随记

在大多数Lua语法分析中可以获得这些标准Lua函数. 无可争辩, 我们可以查阅Lua网站, 但是一些少了的函数被Blizzard进行了调整. 下面列出了所有Lua函数. WoW API中的Lua注意在WoWAPI没有提供所有标准的Lua函数, 很显然, 操作系统以及文件I/O库是不支持的 Lua函数这些函数都是Lua编程语言的一部分, 点击这里了解更多. ?assert(value) - 检查一个值是否为非nil, 若不是则(如果在wow.exe打开调试命令)显示对话框以及输出错误调试信息 ?c

C++访问lua函数性能测试结果

 转载请注明,来自:http://blog.csdn.net/skyman_2001 lua版本是5.1 1. windows平台 CPU: Intel Core i5 3.20GHz 3.60GHz 内存: 8G 操作系统:win7 64位 测试数据:执行125次耗时0.067毫秒 2. ios平台 iPhone 4s 测试数据: (1). debug模式:执行125次耗时1.078毫秒 (2). release模式:执行125次耗时0.669毫秒 C++访问lua函数性能测试结果

cocos2d-x 3.0 在C++中调用lua函数

代码用的是<cocos2d-x 3.0 在lua中调用自定义类>中的代码. 在上篇的基础上进行扩充. 写lua函数 local function process_packet(user_data) if user_data then user_data = tolua.cast(user_data, "user_data"); print (user_data:uid()); print (user_data:uname()); end end local ghall =