50

我最近发现了 Ruby 的块和产生特性,我想知道:这在计算机科学理论方面适合什么?它是一种函数式编程技术,还是更具体的东西?

4

4 回答 4

105

Rubyyield不像 C# 和 Python 那样是迭代器。yield一旦您了解了块在 Ruby 中的工作原理,它本身实际上是一个非常简单的概念。

是的,块是一种函数式编程特性,尽管 Ruby 并不是一种适当的函数式语言。事实上,Ruby 使用该方法lambda来创建块对象,这是从 Lisp 用于创建匿名函数的语法中借用的——这就是块的含义。从计算机科学的角度来看,Ruby 的块(和 Lisp 的 lambda 函数)是闭包。在 Ruby 中,方法通常只占用一个块。(你可以通过更多,但这很尴尬。)

Ruby 中的yield关键字只是一种调用已赋予方法的块的方式。这两个例子是等价的:

def with_log
  output = yield # We're calling our block here with yield
  puts "Returned value is #{output}"
end

def with_log(&stuff_to_do) # the & tells Ruby to convert into
                           # an object without calling lambda
  output = stuff_to_do.call # We're explicitly calling the block here
  puts "Returned value is #{output}"
end

在第一种情况下,我们只是假设有一个块并说调用它。另一方面,Ruby 将块包装在一个对象中并将其作为参数传递。第一个更高效和可读,但它们实际上是相同的。你会这样称呼任何一个:

with_log do
  a = 5
  other_num = gets.to_i
  @my_var = a + other_num
end

它会打印最终分配给@my_var. (好吧,这是一个完全愚蠢的功能,但我想你明白了。)

块在 Ruby 中用于很多事情。几乎每一个你会在像 Java 这样的语言中使用循环的地方,它在 Ruby 中都被替换为带块的方法。例如,

[1,2,3].each {|value| print value} # prints "123"
[1,2,3].map {|value| 2**value}    # returns [2, 4, 8]
[1,2,3].reject {|value| value % 2 == 0} # returns [1, 3]

正如 Andrew 所指出的,它也常用于打开文件和许多其他地方。基本上只要你有一个可以使用一些自定义逻辑的标准函数(比如排序数组或处理文件),你就会使用一个块。还有其他用处,不过这个答案已经这么长了,恐怕会导致体质较弱的读者心脏病发作。希望这可以消除对该主题的困惑。

于 2009-04-19T09:28:34.273 回答
6

除了循环之外,还有更多的收益和阻塞。

Enumerating enumerable系列有一系列你可以用枚举做的事情,比如询问一个陈述是否对一个组的任何成员都为真,或者它是否对所有成员都为真,或者搜索任何或所有满足特定条件的成员.

块对于变量范围也很有用。它不仅方便,还可以帮助进行良好的设计。例如,代码

File.open("filename", "w") do |f|
  f.puts "text"
end

确保文件流在您完成后关闭,即使发生异常,并且一旦您完成该变量就超出范围。

一个随便的谷歌没有想出一篇关于红宝石块和产量的好博客文章。我不知道为什么。

回复评论

我怀疑它是因为块结束而关闭的,而不是因为变量超出范围。

我的理解是,当指向对象的最后一个变量超出范围时,除了该对象有资格进行垃圾收集外,没有什么特别的事情发生。不过,我不知道如何确认这一点。

我可以证明文件对象在被垃圾收集之前就被关闭了,这通常不会立即发生。在下面的示例中,您可以看到在第二puts条语句中关闭了一个文件对象,但它还没有被垃圾回收。

g = nil
File.open("/dev/null") do |f|
  puts f.inspect # #<File:/dev/null>
  puts f.object_id # Some number like 70233884832420
  g = f
end
puts g.inspect # #<File:/dev/null (closed)>
puts g.object_id # The exact same number as the one printed out above,
  # indicating that g points to the exact same object that f pointed to
于 2009-04-19T04:58:05.437 回答
2

我认为该yield语句起源于CLU语言。我一直想知道Tron的角色是否也以CLU命名......

于 2009-04-18T20:29:37.610 回答
0

我认为“协程”是您要查找的关键字。

例如http://en.wikipedia.org/wiki/Yield

计算和信息科学的产出:

  • 在计算机科学中,协程的返回(和重新进入)点
于 2009-04-18T20:34:54.320 回答