为什么ruby循环是这样设计的?

dag*_*ies 1 ruby

正如标题中所述,我很想知道为什么Ruby决定放弃经典for循环而改为使用 array.each do ...

我个人觉得它的可读性稍差,但这只是我个人的看法.无需争论.另一方面,我认为他们是故意设计的,应该有一个很好的理由.

那么,以这种方式放置循环有什么好处?这个设计决定的"存在理由"是什么?

dav*_*dev 7

这个设计决策是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的块,这种简单性很难实现.

我希望这能让你看到这种语言功能有多强大.