- 论坛徽章:
- 5
|
回复 34# OwnWaterloo
Lua这种语言,不可能过多的把精力关注在模块系统上。Haskell的module,import都是语法。Lua怎么办呢?
实际上,Lua5.1的require允许你传递额外参数,所以如果你真就喜欢隐藏参数了,这么干吧…………
主模块:
local function private(module)
if name_is_private(module._NAME) then error("private module") end
return module
end
然后载入的时候:
require("xxxx", private)
不过这个特性在5.2被去掉了,所以……………………
更严重的是,无论你做什么手脚,无论你是不是私有的,模块载入这个行为是全局的,这就意味着,无论是否私有化,无论是否本地化,无论你用任何方式载入的这个库,只要你载入一遍了,你就可以在毫不修改任何默认参数的情况下require第二遍。因为被载入的库会被缓存,第二次载入根本不会再进入模块载入功能了,会直接加载缓存的那个库。也就是说,相对路径载入,根本达不到hide module的功能。你最终载入了plugin.foobar,用户会发现他突然能载入一个“神秘”的模块,叫做plugin.foobar了,而且很好用!突然有个版本这个神秘模块没了,用户傻逼了。
3的答案是不行,Lua没有遍历路径的任何方式。因为ANSI C没有。
4reload理论上做得到,云风就做到了。但是那意味着必须非常非常小心地写模块和框架,要有非常严格的语法限制,具体要花时间总结,而且有一点很重要的是,标准模块机制没用了。或者至少是得做大幅度修改。
我想说说我的观点。BASIC里面有goto,确切地说,1980年的GW-BASIC里面**只有**goto,所以产生了不少面条代码。所以你说goto是坏的,goto是恶魔。到了2012年的今天,有人听到了“goto是恶魔”这句话,于是就说“C语言里面goto是恶魔”,愚昧不?
C里面指针乱指导致内存泄露,于是人们说“Haskell内存不安全,指针乱指容易泄露”,傻逼不?
为什么一门语言的缺陷,就必须是所有语言的缺陷呢?
C模块容易造成安全性的私有模块的问题,仅仅在C模块——因为那在Lua能力范围之外。所以,你有选择是否导出的权利——确切地说,你只有明确地导出才能用。这避免了你喝醉了酒误加了一个参数然后把某个模块公开了——这不可能。你至少得写一打代码做导出。
而Lua模块。为什么我最开始说Lua导出的只有函数?是因为Lua的函数不危险。它们没有上下文。或者说,他们的上下文是死的,是文件里面写死的。Lua的模块机制是“平”的。即使你写a.b.c.d.e.f,到了module.loaded里面也是平的。平的模块机制是无法解决隐藏模块的问题的,也不需要解决隐藏模块问题。Lua无意隐藏任何模块。因为你只要拿出来的模块,就可以公开,出问题了是谁的问题呢?前面说了,社区啥啥啥的。语言为什么要强制某些东西呢?特别的,在Lua这种连参数数目都不强制,连变量声明都不强制的语言里面,你去强制不允许载入某些模块,你不觉得很可笑么?
Lua的哲学是“平面的比递归的好,显式的比隐晦的好”。所以Lua的模块机制是扁平的,Lua的模块载入是显式的(不允许一次载入多个模块如import ..plugins.*这种)。但是,Lua的哲学还有一个“做得到比做不到好”,因此你可以自己实现你想要的模块载入机制——啊啊啊,我知道你想说什么事情了。“这不标准”“你不能强制每个人都用你写的模块载入”,对不对?两个错误。1.Lua的模块机制对模块的要求是最低的。唯一要求是“你得返回你的模块内容”,Over,因此任何人实现的任何模块载入机制,都兼容所有人写的Lua模块。2.事实上有人已经做了,而且得到了官方承认。Lua邮件列表大概一两个月前很热烈的讨论了require的诸多可能,好像还创建了一个项目叫llrequire还是啥的,反正加了很多他们(自以为)很帅的功能,其中就有你的reload——虽然这不现实。
reload的问题,详细说说——你得保证所有模块的使用不会被缓存。就这么简单。但是也不简单。这意味着效率无法得到保证。无论中间加抽象层,还是用查表法调用函数,效率上都无法保证。所以我倾向于不依赖reload,或者在特定的机制上(仅依赖少数接口)的模块进行reload。
Lua的第一设计目标是嵌入式语言,简单是压倒一切的要求。第二设计目标里面,Lua的哲学阻止了实现所谓的私有模块和一次载入一户口本的模块。第二设计目标里面,Lua哲学允许你自己实现这些东西,而且和通用模块兼容,你还想要什么呢?——哦,对了,Lua还提供了实现这些东西的“砖瓦”,无论是package.loadlib(载入dll文件)还是package.searchpath(搜索一系列路径)都给你了,简直就是司马昭之心路人皆知啊………………那你还不动手?
其实自己设计一套载入机制也没什么太大问题,但这是一种很危险的信号:你在将其他语言的经验放入Lua。为什么不按照Lua的思路来,显式地、平面地去载入模块,不要去载入自己不知道的模块呢?如果你知道某个模块,你载入了他,下个版本他消失了,你难道不能从旧版本拷贝一个,放回来么?谁阻止你这么做了呢?
|
|