在 Ruby 中的 yeild 关键字 ( 上 ) 中我们学习了 Ruby 中的 块 ( block ) 的概念和 yield 关键字的基本用法。当然了,上一章节讲的有点太底层了,可能会让还不太熟悉的你一头雾水。
本章节,我们通过一些简单的用例来加深 yield 的用法。
Array#my_map
Enumerable#map
方法允许我们迭代对象列表并操作它们中的每一个元素。 然后返回一个包含所有被操作对象的新列表
$> array = [1, 2, 3] => [1, 2, 3] $> array.map {|n| n + 2} => [3, 4, 5] $> array => [1, 2, 3]
上面的代码中,我们首先给 array
变量赋值 [1,2,3]
。然后我们调用 array.map{|n| n+2 }
将数组中的每个元素都 +2
,然后返回一个新数组 [2,4,6]
。
最后,我们可以看到,原来的数组 array
并没有改变。
接下来。我们尝试在 Array
类上实现我们自己的 Enumerable#map
版本
class Array def my_map ary = [] self.each do |elem| ary << yield(elem) end ary end end $> array = [1, 2, 3] => [1, 2, 3] $> array.my_map {|n| n + 2} => [3, 4, 5] $> array => [1, 2, 3]
从上面的代码中可以看到,我们自定义的 map
方法会行为和官方的 Enumerable#map
是一样的。
超级棒,现在我们来分析下这段代码
- 我们创建一个名为
ary
的临时数组 ( Array )。 该变量将包含我们自定义方法的返回值 - 我们使用
self.each
迭代接收器Array
- 对于每个元素,我们都执行一次
yield(elem)
- 其中elem
是迭代器当前的元素,然后我们把yeild(elem)
的返回值存储到ary
数组中。 - 返回
ary
数组
如果我们不传递块 ( block
) 给我们的 Array#my_map
会发生什么情况么 ?
$> array.my_map LocalJumpError (no block given (yield))
可能正如你所预见的那样,抛出了一个异常。
幸运的是,我们已经在前面的章节中讲解了如何修复这个问题,我们所要做的就是利用 Kernel#block_given?
来增强我们的 Array#my_map
方法
class Array def my_map return self.dup unless block_given? ary = [] self.each do |elem| ary << yield(elem) end ary end end $> array.my_map => [1, 2, 3]
这样,当不传递任何块给 Array#my_map
也不会报错,而且会直接返回原数组的一个拷贝
目前尚无回复