-2

我看到的大多数示例都是微不足道的,我不确定这会给语言增加什么。我明白为什么你会在 Objective-C 中使用块来处理回调或在 Javascript 中使用闭包作为计时器的回调,但我不确定在 Ruby 中我将使用块来做什么。是否可以使用它来代替具有类似功能的功能inject

4

2 回答 2

2

Ruby 到处都使用块,这是该语言最普遍的特性之一。它基本上是函数即值的优化案例。一个真正的函数对象,就像在 JavaScript 中一样,在 Ruby 中是一个Proc类的实例。块不是对象,因此避免了对象性产生的一些开销。原因是,在几乎所有你想将函数作为参数传递的情况下,你只会传递一个,并且你想当场定义它,所以为什么不优化,让事情成为语法上更好一点?

这是一个块:

[1, 2, 3].each do |i|
  puts i
end

这是一个函数:

func = Proc.new do |i|
  puts i
end
[1, 2, 3].hypothetical_each(func)

您可以看到,即使定义一个函数值也涉及一个块(作为Proc构造函数的参数)。

您通常在 中使用块inject,而不是函数。您几乎在 Ruby 中的每个循环结构中都使用它(while非常不常用)。

您还可以使用块来构建特定领域的语言,例如 Sinatra:

get 'index.html' do
  "Hello World"
end

或 Rspec:

describe "addition" do
  it "should add two numbers together" do
    (1+2).should equal(3)
  end
end

学好积木,因为没有积木你就不能读,也不能写好 Ruby。

于 2012-12-25T03:59:01.023 回答
0

ruby 中块的秘密在于 ruby​​ 设计的本质。

Ruby 设计有一个对象模式,其中方法调用作为“消息”发送到对象,返回值是响应。在 ruby​​ 中(与 python 和其他一些语言不同),函数和方法本身不是对象。块是 ruby​​ 在此模式中允许类似函数的消息的方式,并且是 ruby​​ 通常如何处理迭代的关键。

如果我错了,请有人纠正我,但我相信实际上不可能在不创建块或使用 while 语句的情况下在 ruby​​ 中进行任何迭代,实际上该for i in object符号只是访问对象each方法的语法简写。

IE。

for i in 1..5
  #do stuff with i
end

执行完全一样:

1..5.each do |i|
  #do stuff with i
end

通过 ruby​​ VM,其中 Range 对象1..5(包括 ruby​​ 标准 lib Enumerable 模块)将其元素生成给传递的块

在引擎盖下,这个操作看起来像这样(注意这是一个简化版本,没有考虑到范围的 ... 独占和 .. 包含版本)

class Range

  def init(start, end)
    @start = start
    @end = end
  end

  def each
    i = @start
    while i < @end
      yield i
      i += 1
    end
  end

end

因此,当调用该 for 循环时,它会创建一个范围对象obj = Range.new(1,5),然后向该对象发送一条消息,obj.send(:each, &block)并在每个方法内部使用一个 while 循环并屈服于块

TL;博士

Ruby 在内部使用块,因为它们对它的设计至关重要,没有它们,语言本身将无法使用它的message => object => response模态。

所以你不应该问:“我为什么要使用积木?” 因为没有它们就无法编写 ruby​​ 程序。

相反,您应该问:“ruby 中的块与 Objective-C 和 Javascript 中的块有何不同?” 因为他们是不同的。

我不能为 Objective-C 说话,但在 JavaScript 中,块在很大程度上是一个对象。它是代码的容器,其他对象可以获取并使用它来做任何需要的事情,块甚至不必与使用它的对象相关联。

在 ruby​​ 中,一个块更像是一个对象在邮件中收到的一组指令,它在它自己上使用(然后在他下次来的时候传递给邮件人)

于 2012-12-25T09:46:45.387 回答