庇护祝福的分享

Be worthy

Ruby元编程三:代码块

闭包

块可以作为一个闭包. 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