Chinaunix首页 | 论坛 | 博客
  • 博客访问: 854973
  • 博文数量: 188
  • 博客积分: 4433
  • 博客等级: 上校
  • 技术积分: 1905
  • 用 户 组: 普通用户
  • 注册时间: 2008-11-14 07:14
个人简介

linux

文章分类

全部博文(188)

文章存档

2016年(6)

2015年(22)

2014年(18)

2013年(5)

2012年(125)

2011年(10)

2010年(2)

分类: 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。但是在PerlLua中就不会发生,原因就在于当解析器发现函数调用的最后一行是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()
然后整个状态机就自动地运行下去了,节省了大量通常的状态机编程需要考虑的状态存储、对象设计问题。

阅读(1609) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~