驭风万里无垠

ruby学习笔记《二》

ruby的blocks和closure特性明显有别于其它的语言,其closure本身是real closure,所绑定的context是共享的而非copy,其设计思路和lisp的相同;blocks本身则可以用于实现closure。二者的关系如下所述 (来源

Yukihiro Matsumoto: You can reconvert a closure back into a block, so a closure can be used anywhere a block can be used. Often, closures are used to store the status of a block into an instance variable, because once you convert a block into a closure, it is an object that can by referenced by a variable. And of course closures can be used like they are used in other languages, such as passing around the object to customize behavior of methods. If you want to pass some code to customize a method, you can of course just pass a block. But if you want to pass the same code to more than two methods -- this is a very rare case, but if you really want to do that -- you can convert the block into a closure, and pass that same closure object to multiple methods.
  • 7种结构

  • block方式3种
  • 隐式传入,内部用yield调用
  
def thrice
  
yield
  
yield
  
yield
end

x
=1
thrice {x
+=2}
  • &block参数传入,内部直接操作&block
def six_times(&block)
  thrice(
&block)
  thrice(
&block)
end
 
= 4
six_times { x 
+= 10 }
  • &block传入,保存block为变量,然后调用block.call
def save_for_later(&b)
  @saved 
= b  # Note: no ampersand! This turns a block into a closure of sorts.
end
 
save_for_later { puts 
"Hello!" }
puts 
"Deferred execution of a block:"
@saved.call
@saved.call
这里的saved保存为main对象的一个成员,后边实现延迟调用。
  • Proc.new/proc
@saved_proc_new = Proc.new { puts "I'm declared with Proc.new." }
@saved_proc 
= proc { puts "I'm declared with proc." }

@saved_proc_new.call
@saved_proc.call
  • lambda
@saved_lambda = lambda { puts "I'm declared with lambda." }
@saved_lambda.call
  • method
def some_method
  puts 
"I'm declared as a method."
end
@method_as_closure 
= method(:some_method)

  • 特点和差异

    • return行为

当对应的block里边包含return的时候,上述7中方式有些许的不同:
  • lambda/method表现出真正的closure行为,仅仅返回closure本身;外部调用控制流不受影响,继续yield或者call的下一语句执行
  • 其它几种会跳出外部调用者的控制流,即return出调用者,yield/call之后的也不会再执行,直接跳出到最近的end外


  • arity - 参数个数校验

对于调用点的参数检查,呈现如下行为:
  • lambda/method严格校验参数的个数,如果不匹配回抛出异常
  • 其它几个不检查参数个数


  • 总结

lambda/method方式呈现完备的closure行为,return之后继续下一流程,对于实际传入参数个数会在调用点检查;proc/blocks方式在return的时候直接返回了外部的函数或者block,对于传入的参数个数也没有执行检查。

参考:http://innig.net/software/ruby/closures-in-ruby
以上结论验证于最新的ruby1.9.3,和链接中的结论有些许不同;ruby1.8中的proc函数可能有不同的行为。

posted on 2012-02-19 19:29 skyscribe 阅读(426) 评论(0)  编辑 收藏 引用 所属分类: Misc


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理


<2024年4月>
31123456
78910111213
14151617181920
21222324252627
2829301234
567891011

导航

统计

常用链接

留言簿(3)

随笔分类

随笔档案

搜索

最新评论

阅读排行榜

评论排行榜