正如标题中所述,我很想知道为什么Ruby决定放弃经典for循环而改为使用 array.each do ...
我个人觉得它的可读性稍差,但这只是我个人的看法.无需争论.另一方面,我认为他们是故意设计的,应该有一个很好的理由.
那么,以这种方式放置循环有什么好处?这个设计决定的"存在理由"是什么?
这个设计决策是Ruby如何结合面向对象和函数式编程范例的完美例子.它是一个非常强大的功能,可以生成简单易读的代码.
它有助于了解正在发生的事情.当你运行:
array.each do |el|
#some code
end
Run Code Online (Sandbox Code Playgroud)
您正在调用对象的each方法array,如果您认为该变量名称,则该方法是Array该类的实例.您正在将代码块传递给此方法(块相当于一个函数).然后,该方法可以评估此块并通过使用block.call(args)或传递参数yield args.each简单地遍历数组,对于每个元素,它调用您传入的块作为参数.
如果each是使用块的唯一方法,这将不是那么有用,但许多其他方法,你甚至可以创建自己的方法.例如,数组有一些迭代器方法,包括map,每个迭代器方法都相同但返回一个包含块的返回值的select新数组,并返回一个新数组,该数组只包含块返回的旧数组的元素真实的价值.使用传统的循环方法,这些事情会很繁琐.
这是一个如何使用块创建自己的方法的示例.让我们创建一个every方法,它有点像地图,但只对数组中的每n个项目.
class Array #extending the built in Array class
def every n, &block #&block causes the block that is passed in to be stored in the 'block' variable. If no block is passed in, block is set to nil
i = 0
arr = []
while i < self.length
arr << ( block.nil? ? self[i] : block.call(self[i]) )#use the plain value if no block is given
i += n
end
arr
end
end
Run Code Online (Sandbox Code Playgroud)
此代码允许我们运行以下代码:
[1,2,3,4,5,6,7,8].every(2) #= [1,3,5,7] #called without a block
[1,2,3,4,5,6,7,8,9,10].every(3) {|el| el + 1 } #= [2,5,8,11] #called with a block
Run Code Online (Sandbox Code Playgroud)
块允许表达语法(通常称为内部DSL),例如,Sinatra web微框架.Sinatra使用块的方法来简洁地定义http交互.例如.
get '/account/:account' do |account|
#code to serve of a page for this account
end
Run Code Online (Sandbox Code Playgroud)
没有Ruby的块,这种简单性很难实现.
我希望这能让你看到这种语言功能有多强大.
| 归档时间: |
|
| 查看次数: |
154 次 |
| 最近记录: |