您的位置:首页 > 编程语言 > Ruby

<<Ruby元编程>>第三章笔记

2014-03-05 10:30 246 查看
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 &操作符
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: