perl python ruby_perl,lua,python,ruby的对比(3) -- lambda,closure,proper tail function call

这篇博客探讨了Perl、Lua、Python和Ruby四种脚本语言中匿名函数、闭包的概念及其应用。匿名函数在各语言中的实现方式不同,而闭包则用于保存外部变量,常见于回调函数和迭代器。此外,文章还提到了Perl和Lua中的propertail call特性,允许函数返回自身调用,避免了栈溢出的问题,这对于构建状态机等场景非常有用。

今天的题目是函数,先看一下匿名函数。

Perl里是这样的

$f = sub{ return $_[0]+$_[1]+$_[2];

};

print &$f(1,2,3)."\n";

lua里是这样的

f = function(x,y,z) return x+y+z end

print (f(1,2,3))

python里使用了lambda概念,实现是这样的,也可以通过全局函数apply调用任意的函数

f = lambda x,y,z : x+y+z

print f(1,2,3)

#or print apply(f, 1, 2, 3)

ruby没有仔细看过,似乎必须这样。可能由于ruby中所有的东西都是对象,所以一定要一个显式的call来调用函数,也可以使用send方式

f = proc { |x,y,z| print x+y+z

}

f.call(1,2,3)

#or the small talk way

#f.send "call", 1, 2, 3

#k.send :call, 1, 2, 3

再看Closure,Closure这个概念很难解释,但是在脚本语言里的作用非常大,现在的脚本语言无一例外的支持它。主要的用途在于Callback函数和iterator中,也就是需要在一个函数需要保留一些外界的value时,提供一个轻量级的方案。对象方法也能提供类似的功能,像C++中STL的iterator就是用inner

class实现的,C中的回调函数通常需要传递一个对象指针,在脚本语言中完全没有必要这么复杂。各种语言实现基本一致,详细的例子可以看看类似iterator的实现代码或者Qt\GTK\wxWindows之类的脚本类库,看一个简单的例子。

Perl的实现

sub CreateObj

{

# parameter

my ($str) = @_;

# This is the closure function that saves external str

value

$callback = sub {

print "$str called\n";

};

return $callback;

}

$call = CreateObj("CB1"); &$call();

python里的实现

def CreateObj(str):

def callback(): print str," called"

return callback

call = CreateObj("CB1")

call()

lua里的实现

function CreateObj(str)

function callback()

print (str.." called")

end

return callback

end

call = CreateObj("CB1")

call

ruby里的实现

def CreateObj(str)

# use proc object instead of anonymous function

return proc { || print str, " called"

}

end

p1 = CreateObj("CB1")

p1.call()

最后看一个有趣的特性,叫做Proper tail call。看下面的伪代码

function test()

begin

return test()

end

这是一个典型的死循环递归调用,在绝大多数语言中类似的调用很快就会导致Stack

Overflow。但是在Perl和Lua中就不会发生,原因就在于当解析器发现函数调用的最后一行是return一个函数调用时,它就会很“智能地”把这个调用延后到函数返回之后再调用,这样就避免了堆栈溢出的问题。所以下面两段代码也不会出问题。

Perl的代码

sub cycle{

print "s\n";

return cycle();

};

cycle();

lua的代码

function cycle()

local dir = io.read()

print (dir)

return cycle()

end

cycle()

上面的例子也许没有什么实际用处,仔细想想这个特性在构造状态机之类的功能是非常有用的,比如一个状态机有三个状态,lua里可以这样写

function state1()

input = getinput()

if (input == 2) then

return state2()

end if (input == 3) then

return state3()

end end

function state2()

input = getinput()

if (input == 1) then

return state1()

end if (input == 3) then

return state3()

end end

function state3()

input = getinput()

if (input == 1) then

return state1()

end if (input == 2) then

return state2()

end end

给定一个初始状态

init = state1()

然后整个状态机就自动地运行下去了,节省了大量通常的状态机编程需要考虑的状态存储、对象设计问题。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值