lua 区间比较_云风的 BLOG

姑且我们把这种技术叫做代码模版吧,对于 C 程序员,则更接近于宏替换,C++ 程序员看来可能是一个高级 template 技巧。不过 lua 能做的更强一些。

我来演示一下,代码模版的上下文变量。

| ALPHA = math.pi / 4 |

function foo(a)

return a * math.sin(|ALPHA|)

end

这个例子里,一开始给代码模版变量 ALPHA 赋了值为 pi/4 。然后在下面的函数中,使用了这个变量。这段代码经过处理后,会把常量 0.78539816339745 (pi/4) 直接编译进入最终执行的代码。而 ALPHA 这个变量,将只在模版预处理期间可见。

下面再看一个更实用一点的例子。

有时候,我们需要一个增强版的 unpack 。我们知道,lua 自带的 unpack 可以把一直数组(只有连续数字下标的 table)展开成一串返回值,但是对用字符串或别的东西做 key 的 table 无能为力。

function unpackex(tbl,args)

local ret={}

for _,v in ipairs(args) do

table.insert(ret,tbl[v])

end

return unpack(ret)

end

下面我们可以用这个函数展开一个数组,

print ( unpackex( { one=1,two=2,three=3 }, { "one","two","three" } ))

unpackex 将按第 2 个参数表中给出的字符串次序解开第一个参数表。这里我们将看到输出 1,2,3 。

btw, 如果你真的需要一个高效的 unpackex ,推荐用 C 来实现,这样能省掉其中的临时 table ret 。

接下来,我们在使用 unpackex 时,还有可能遇到一个性能问题。因为第二个参数表通常是个常量数组,但由于 lua 的语义,下列函数中的这个常量表,可能在每次进入函数 foo 时构造一个新的出来。

function foo(tbl)

return unpackex(tbl,{"one","two","three"})

end

如果 foo 对性能很敏感,有经验的 lua 程序员或许会这样优化一下:

local const_list={"one","two","three"}

function foo(tbl)

return unpackex(tbl,const_list)

end

但这破坏了代码的直观。如果有了代码模版,我们实际上可以写成这样:

function foo(tbl)

return unpackex(tbl,| {"one","two","three"} |)

end

ok. 现在基本能看出来这个代码模版做了些什么。

它在分析源码字符串时,碰到 | 夹住的部分,将立即运行,获得结果。如果没有结果(例如只是运行一些代码,无返回值),则跳过。如果有结果值(可以由 return 返回,也可以本身是一个表达式),先判断类型是否是一个简单类型(nil ,boolean ,number 或 string ),就把值直接插入源码。如果是一个复杂类型,则创建一个 local 变量记住结果,并将这个 local 变量插入代码。

这里,简单类型 string 会被加上 [=[ 这样的括号插入。而有时候,我们需要直接把字符串插进去。

例如,有时候我们期望 lua 有 C 的 include 那种功能,直接把一文本文件插入源码。

为了效率,我们通常在每个 .lua 文件最前面写上诸如:

local pairs=pairs

local table=table

local string=string

这样的语句。

这可以提高 lua 程序访问内置 api 的效率(减少一次对全局表的查询)。

但每个文件前都写这么一串过于繁琐,也容易出错。如果有 include 功能就好了。那么就让我们实现一个:

function include(filename)

local f=assert(io.open(filename))

local ret=f:read "*a"

f:close()

return ret

end

这个函数可以读入一段文本返回。

代码模版可以通过 |# include "local.lua"| 这样的语法,将 include 函数的返回值插入代码。(注:遇到 | 后紧跟一个 # ,这个区间的返回值就必须是一个 string ,并且这个 string 将被插入代码)

最后,来看看代码模版的实现吧,使用 lua 本身就可以轻易搞定。有兴趣的同学点这里。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值