linux
分类: Python/Ruby
2012-02-13 15:57:52
http://blog.sina.com.cn/s/blog_496e4a970100micj.html
今天的题目是函数,先看一下匿名函数。
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()
然后整个状态机就自动地运行下去了,节省了大量通常的状态机编程需要考虑的状态存储、对象设计问题。