1 块是一种控制作用域(scope)的强大手段,作用域指的是哪些代码可以看到哪些变量和方法.
2
只有在调用一个方法时才可以定义一个块.块会被直接传递给这个方法,然后该方法可以用yield关键字回调这个块.
3
块中最后一行代码执行的结果会被作为返回值.
4
在一个方法中,可以向Ruby询问当前的方法调用是否包含快,可以通过Kernel#block_given?()方法来做到:
def
a_method
return yield if block_given?
‘no block‘
end
a_method #=> no block
a_method {"here‘s a block!"}
#=> here‘s a block!
作用域小结:
1 每个Ruby作用域包含一组绑定,并且不同的作用域之间被作用域门分隔开来:class,module和def.
2
如果要让一两个绑定穿越作用域门,那么可以用方法调用来替代作用域门:用一个闭包获取当前的绑定,并把这个闭包传递给该方法.可以用Class.new()方法代替class,使用Module.new代替module,以及使用Module#define_method()代替def.这就形成了一个扁平作用域,它是闭包中的一个基本概念.如果在一个扁平作用域中定义了多个方法,则这些方法可以用一个作用域门进行保护,并共享绑定,这种技术称为共享作用域.
Object#instance_eval() 方法: 在一个对象的上下文中执行一个块.
可以把传递给instance_eval()方法的块称为一个上下文探针,因为它就像是一个深入到对象中的代码片段,对其进行操作.
class MyClass
def initialize
@v =
1
end
end
obj = MyClass.new
obj.instance_eval do
puts
self #=>#<MyClass:0x23e7a90>
puts
@v #=> 1
end
v = 2
obj.instance_eval{@v =
v}
obj.instance_eval{puts @v} #=> 2
可调用对象:
1
一个Proc就是一个转换成对象的块,可以通过把块传给Proc.new方法来创建一个Proc,以后就可以用Proc#call()方法来执行这个由块转换而来的对象:(延迟执行)
inc
= Proc.new{|x| x + 1}
inc.call(2) #=>3
2 还有两个内核方法可以把块转换为Proc: lambda()和proc().
dec = lambda{|x| x -
1}
dec.class #=> Proc
dec.call(2) #=>1
3
`想把这个块传递给另外一个方法.
`想把这个块转换为一个Proc.
在这两种情况下,都需要指着那个块说:"我想用这个块"
.为了做到这一点,需要给块取一个名字.要将块附加到一个绑定上,可以给这个方法添加一个特殊的参数,这个参数必须是参数列表中的最后一个,且以&符号开头.
&操作符的真正含义:这是一个Proc对象,我想把它当成一个块来使用.去掉&操作符,就能再次得到一个Proc对象.
def
my_method(&the_proc)
the_proc
end
p = my_method {|name|
"hell,#{name}"}
puts p.class #=>Proc
puts p.call("bill") #=> hello
bill
可调用对象小结
可调用对象是可以执行的代码片段,而且它们有自己的作用域.可调用对象可以有以下几种方式:
1 块:在定义它们的作用域中执行.
2
proc:Proc类的对象,跟块一样,它们也在定义自身的作用域中执行.
3
lambda:也是Proc类的对象,但是它跟普通的proc有细微的区别.它跟块和proc一样都是闭包,因此也在定义自身的作用域中执行.
4
方法:绑定于对象,在所绑定对象的作用域中执行.它们也可以与这个作用域解除绑定,再重新绑定打另一个对象的作用域上.
不同可调用对象的区别:
1 在lambda和方法中,return语句从可调用对象中返回.
2
不同的可调用对象对传入参数数目校验有不同的反应.其中方法处理方式最严格,lambda同样严格,而proc和块则要宽松一些.
不同的可调用对象之间的转换:
1 Proc.new()方法
2 Method#to_proc()方法
3
&操作符
<<Ruby元编程>>第三章笔记,布布扣,bubuko.com
原文:http://www.cnblogs.com/leaf526/p/3581879.html