在ruby中代码块是在大括号和do-end中间的部分,代码块只能出现在一个方法的后边,它紧接在方法最后一个参数的同一行上。代码块的内容并不会被马上执行,当执行到被调用的方法时,解释器的运行时环境会记住代码块出现的现场,然后执行被调用的方法。
[1,2,3,4,5].each { |i|
puts i
}
[1,2,3,4,5].each do |i|
puts i
end
一般的使用习惯是:(to-do 具体解释)
l 当关心边际(side effect)效应时使用 do/end。
l 当关心返回结果应时使用大括号。
****** {} 和 do end 前者优先级高。
Proc类和代码块的关系:
代码块并不是对象,但可以方便的转化为Proc类的对象。有三种转化的方法:
①将一个代码块传递给最后一个参数以&开始的方法。不是很明白?????
def meth1(p1, p2, &block)
puts block.inspect
puts block.call
end
meth1(1, 2) { "This is a block" }
② 使用Proc.new方法,后边的参数为一个代码块:
block = Proc.new { puts "a block" } # 代码不会运行
block.call #现在我们调用Proc存放的代码
#结果: a block
③ 调用Kernel.lambda方法:
block = lambda { "a block" }
前两种方法是等价的,而第三种方法,用 lambda 生成的 Proc 对象和用 Proc.new 生成的 Proc 对象之间是有差别的。这是一个微妙的差别,这个差别与 return 关键字相关。lambda 中的 return 从 lambda 返回。而 Proc 中的 return 从外围方法返回。
可以看以下两个例子:
def test_proc
p = Proc.new { return 1 }
p.call
puts "Never come here"
end
test_proc #=> 1
执行后"Never come here"不会被输出,执行p.call相当于在test_proc方法内执行了return语句。既是在Proc 中的 return 从外围方法返回;
def test_lambda
p = lambda { return 1 }
result = p.call
puts "The value is: #{result}"
end
test_lambda
执行后的结果为:
The value is: 1
可见使用lambda生成的Proc对象执行call方法调用时,return表示从lambda包围的块内返回。return 从 lambda 返回;
向Proc和Block中传递参数 (向Proc和Block中传递参数的方式是一样的)
def dumb_hello_world_test
yield(5)
end
dumb_hello_world_test {|i| puts i * 2 }
# => 10
my_silly_proc = Proc.new {|name| puts name.upcase }
my_silly_proc.call("August Lilleaas")
# => "AUGUST LILLEAAS"