手机浏览 RSS 2.0 订阅 膘叔的简单人生 , 腾讯云RDS购买 | 超便宜的Vultr , 注册 | 登陆
浏览模式: 标准 | 列表Tag:lua

转:lua 5.2 的 _ENV

这篇文章是云风的博客上的文章,知道云风是在做游戏,也知道他一直在做lua、C的开发。
我也是最近才刚刚开始看lua,主要是看了一眼之后就发现,原来lua,连函数的写法,对象的格式(tabledata),几乎都一样。所以,在开始关注着。
今天看到这篇文章,转贴是因为,看到云风写的这段代码:

XML/HTML代码
  1. function foobar(env)  
  2.     return setfenv(  
  3.     function()  
  4.         local ret = {}  
  5.         function ret.foo()  
  6.             ...       
  7.         end  
  8.         function ret.bar()  
  9.             ...  
  10.         end  
  11.         return ret  
  12.     end , env) ()  
  13. end  

超级象javascipt,比如可以写成:

XML/HTML代码
  1. function foobar(env){  
  2.     return setfenf(function(){  
  3.         var ret = {};  
  4.         ret.foo = function(){};   
  5.         ret.bar = function(){};  
  6.         return ret;  
  7.     },env)();  
  8. }  

感觉有点超象。。。
上原文了。地址:http://blog.codingnow.com/2011/12/lua_52_env.html

lua 5.2 正式发布了,对于 lua 语言本身的修改,重中之重就是对 environment 这个概念的修改。

可以说, 5.1 以前的 environment 已经没有了。environment 对于制造一个安全的沙盒(或是实现 DSL)是一个很重要的语言特性,我以前很喜欢使用,但也很容易用错。这次的修改我认为是一个谨慎的决定,并使得 lua 语言更为精简和严谨了。

我这样理解 5.2 中的 environment 。本质上,lua 取消了原有意义上的 environment 。所以我们可以看到 C Function 不再有环境了。function 、在 lua 中称为 closure ,仅仅只是函数体和 upvalue 的联合体。这简化了 lua 语言本身。全局变量实际上只是一个语法糖,编译时再前面加上了 _ENV. 的前缀。这样,从 load 开始,第一个 chunk 就被加上了 _ENV 这个 upvalue ,然后依次传递下去。

这个设计基本可以取代以前使用 getfenv/setfenv 改变函数环境的方法。但是又不完全等价。总体来说,增加了一些限制,但不太容易写出 bug 的代码了。

比如说,现在想给返回一个独立环境的函数,可以这样写:

function foobar(env)     local _ENV = env     return function() ... end end

而以前大约是这样:

function foobar(env)     return setfenv(function() ...  end, env) end

这不太看得出好坏,但是如果是一组函数,就有区别了。5.2 中是这样:

function foobar(env)     local _ENV = env     local ret = {}     function ret.foo()         ...          end     function ret.bar()         ...     end     return ret end

5.1 的等价代码大约是这样:

function foobar(env)     local old = getfenv()     setfenv(1,env)     local ret = {}     function ret.foo()         ...          end     function ret.bar()         ...     end     setfenv(1,old)     return ret end

或者这样更函数式一点:

function foobar(env)     return setfenv(     function()         local ret = {}         function ret.foo()             ...              end         function ret.bar()             ...         end         return ret     end , env) () end

getfenv/setfenv 更灵活,却更容易出错。

对于制作沙盒来说,我感觉 lua 5.2 会更为鼓励使用 load 这种运行时的编译行为。即一定程度上的鼓励元编程。(因为取消了 setfenv ,所以给了 load 显式的参数来制定给 chunk 一个新的环境)

btw, 这个语言设计变更的同时也增强了函数式编程的性能。因为 lua 现在可以更方便的合并那些有相同 upvalue 的 closure 了。(从前除了 upvalue 还有 environment ,合并行为更为复杂)


12 月 30 日补充:

如果非要类似 setfenv 的功能, 修改一组函数的 _ENV 大概需要这样做了:

function getfuncs()   local _ENV = _ENV   local ret = {}   function ret.foo()     ...   end   function ret.setfenv(env)     _ENV = env   end   return ret  end

Tags: lua, 云风

在 Mac OS X 上安装 32bit Lua + LuaSocket

妖怪的文章,用作参考:http://dualface.qeeplay.com/index.php/archives/1415
原文如下:

由于 OS X 是 64bit 操作系统,所以默认情况下编译出来的 Lua 是 64bit 的。一般应用不会有任何问题,但使用 luac 编译源代码后得到的字节码就只能在 64bit 操作系统中使用。

我使用 Lua 的主要目的是在 iOS/Android 环境中简化游戏开发,因此必须在 OS X 中编译出 32bit 的 Lua 及相关库。

下载 lua 5.1.4 源代码和 5.1.4-3 patch:

XML/HTML代码
  1. $ wget http://www.lua.org/ftp/lua-5.1.4.tar.gz  
  2. $ tar zxf lua-5.1.4.tar.gz  
  3. $ wget -O lua-5.1.4-3.patch http://www.lua.org/ftp/patch-lua-5.1.4-3  
  4. $ cd lua-5.1.4/src  
  5. $ patch < ../../lua-5.1.4-3.patch  

编辑 lua-5.1.4/src/Makefile,将:

XML/HTML代码
  1. macosx:  
  2.         $(MAKE) all MYCFLAGS=-DLUA_USE_LINUX MYLIBS="-lreadline"  

改为:

XML/HTML代码
  1. macosx:  
  2.         $(MAKE) all MYCFLAGS="-DLUA_USE_LINUX -arch i386" MYLIBS="-lreadline -arch i386"  

最后:

XML/HTML代码
  1. $ cd lua-5.1.4  
  2. $ make macosx  
  3. $ sudo make install  
然后,就安装到/usr/local/ 下面了。
这是执行make install后显示在屏幕上的,先记录下来,以后可以做参考【膘叔】
  1. cd src && mkdir -p /usr/local/bin /usr/local/include /usr/local/lib /usr/local/man/man1 /usr/local/share/lua/5.1 /usr/local/lib/lua/5.1  
  2. cd src && install -p -m 0755 lua luac /usr/local/bin  
  3. cd src && install -p -m 0644 lua.h luaconf.h lualib.h lauxlib.h ../etc/lua.hpp /usr/local/include  
  4. cd src && install -p -m 0644 liblua.a /usr/local/lib  
  5. cd doc && install -p -m 0644 lua.1 luac.1 /usr/local/man/man1  

 

 

下载 LuaSocket 2.0.2:

XML/HTML代码
  1. $ wget http://files.luaforge.net/releases/luasocket/luasocket/\  
  2. luasocket-2.0.2/luasocket-2.0.2.tar.gz  
  3. $ tar zxf luasocket-2.0.2.tar.gz  
  4. $ cd luasocket-2.0.2  

打开 config 文件,修改为(使用 Mac OS X 的设定,并指定 32bit 架构):

XML/HTML代码
  1. LUAINC=-I/usr/local/include/lua5.1  
  2.   
  3. #------  
  4. # Compiler and linker settings  
  5. # for Mac OS X  
  6. #  
  7. CC=gcc  
  8. DEF= -DLUASOCKET_DEBUG -DUNIX_HAS_SUN_LEN  
  9. CFLAGS= $(LUAINC) -I$(COMPAT) $(DEF) -pedantic -Wall -O2 -fno-common -arch i386  
  10. LDFLAGS=-bundle -undefined dynamic_lookup -arch i386  
  11. LD=export MACOSX_DEPLOYMENT_TARGET="10.7"; gcc  
  12.   
  13. #------  
  14. # Compiler and linker settings  
  15. # for Linux  
  16. #CC=gcc  
  17. #DEF=-DLUASOCKET_DEBUG  
  18. #CFLAGS= $(LUAINC) $(DEF) -pedantic -Wall -O2 -fpic  
  19. #LDFLAGS=-O -shared -fpic  
  20. #LD=gcc  

最后编译安装即可:

XML/HTML代码
  1. $ make  
  2. $ sudo make install  
-----EOF--

如果你不是特别需要安装32位的lua,那么妖怪那段增加 -arch i386这一段的内容就可以不需要改动了。嗯。就是这样简单。

但真的这样吗?NND,事实上我在按照上面操作的时候,告诉我wget这个函数不存在,我晶啊,wget居然不是标配。

最后只能用curl解决了这个问题,把wget http://xxxx.xxx/xxx.xxx.gz 改为:curl http://xxx.xxx/xxx.gz -O xxx.gz,OK,就完成了。。

然后利用这样的操作也下载了一份wget,搞定。还是wget更方便,因为它很简单。。。

 

 

 

Tags: lua