闭包
块可以作为一个闭包. example:
def my_method
x="Goodbye"
yield("cruel")
end
x = "Hello"
my_method {|y| "#{x} , #{y} world"} #=>Hello, cruel world
块获得了局部绑定的变量x,并一直带着它。块并不能接受方法中定义的x=”Goodbye”
作用域与作用域门
程序会在三个地方关闭前一个作用域,同时打开一个新的作用域: 类定义 模块定义 方法 它们分别用关键字class,module,def为标志每一个关键字都充当了一个作用域门。
Proc类,proc,lambda , yield , &操作符
将块转化为对象
使用块需要分两步:1.把块的逻辑写好打包备用。2.调用块
块不是对象,如果想要存储一个块供以后执行,需要一个对象。
Ruby标准库提供Proc类,它接受一个块作为参数,从而将这个块转化为对象:
inc = Proc.new { |x| x+1}
inc.call(2) #=>3
而lambda , proc 本质也是将块转化为Proc类的实例化对象
lambda,proc的区别
1.使用return关键字的时候,lambda从它本身返回,而proc则会在定义它的作用域中返回。
def double(param)
param.call*2
end
l=lambda {return 10}
double(l) #=>20
p=proc {return 10}
double(p) #=>报错LocalJumpError
2.参数数量 调用lambda的时候,如果参数数量不对则会报错,而proc会自动调整,忽略多余的,如果少了则会将其赋为nil
&操作符
它可以实现: 1.把这个块传递给另一个方法 2.把一个块转化为proc,只需要去掉&操作符即可。
example1:
def math(a, b)
yield(a , b)
end
def teach_math(a , b , &block)
puts math(a , b , &black)
end
teach_math(2,3) {|x ,y| x*y} #=>6
example2:
def test(&block)
block
end
t=test {|name| "Hello,#{name}"}
puts t.call("Tom") #=>Hello , Tom