Ruby 的产量特性与计算机科学的关系
我最近发现了 Ruby 的块和屈服特性,我想知道:这在计算机科学理论中适合什么? 它是一种函数式编程技术,还是更具体的技术?
I recently discovered Ruby's blocks and yielding features, and I was wondering: where does this fit in terms of computer science theory? Is it a functional programming technique, or something more specific?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
Ruby 的
yield
不是像 C# 和 Python 中那样的迭代器。 一旦您了解了块在 Ruby 中的工作原理,yield
本身实际上是一个非常简单的概念。是的,块是一种函数式编程特性,尽管 Ruby 并不是一种真正的函数式语言。 事实上,Ruby 使用 lambda 方法来创建块对象,该方法借用自 Lisp 创建匿名函数的语法——这就是块。 从计算机科学的角度来看,Ruby 的块(以及 Lisp 的 lambda 函数)是闭包。 在 Ruby 中,方法通常只占用一个块。 (您可以传递更多,但这很尴尬。)
Ruby 中的
yield
关键字只是调用已赋予方法的块的一种方式。 这两个例子是等价的:在第一种情况下,我们只是假设有一个块并说调用它。 在另一种情况下,Ruby 将块包装在一个对象中并将其作为参数传递。 第一个更高效、更易读,但它们实际上是相同的。 您可以像这样调用其中任何一个:
它会打印最终分配给
@my_var
的值。 (好吧,这是一个完全愚蠢的函数,但我想你已经明白了。)块在 Ruby 中用于很多事情。 在 Java 等语言中,几乎所有需要使用循环的地方,在 Ruby 中都被采用块的方法所取代。 例如,
正如安德鲁所指出的,它也常用于打开文件和许多其他地方。 基本上,只要您有一个可以使用某些自定义逻辑(例如对数组进行排序或处理文件)的标准函数,您就会使用块。 还有其他用途,不过这个答案已经这么长了,恐怕体质较弱的读者会心脏病发作。 希望这能消除对此主题的困惑。
Ruby's
yield
is not an iterator like in C# and Python.yield
itself is actually a really simple concept once you understand how blocks work in Ruby.Yes, blocks are a functional programming feature, even though Ruby is not properly a functional language. In fact, Ruby uses the method
lambda
to create block objects, which is borrowed from Lisp's syntax for creating anonymous functions — which is what blocks are. From a computer science standpoint, Ruby's blocks (and Lisp's lambda functions) are closures. In Ruby, methods usually take only one block. (You can pass more, but it's awkward.)The
yield
keyword in Ruby is just a way of calling a block that's been given to a method. These two examples are equivalent:In the first case, we're just assuming there's a block and say to call it. In the other, Ruby wraps the block in an object and passes it as an argument. The first is more efficient and readable, but they're effectively the same. You'd call either one like this:
And it would print the value that wound up getting assigned to
@my_var
. (OK, so that's a completely stupid function, but I think you get the idea.)Blocks are used for a lot of things in Ruby. Almost every place you'd use a loop in a language like Java, it's replaced in Ruby with methods that take blocks. For example,
As Andrew noted, it's also commonly used for opening files and many other places. Basically anytime you have a standard function that could use some custom logic (like sorting an array or processing a file), you'll use a block. There are other uses too, but this answer is already so long I'm afraid it will cause heart attacks in readers with weaker constitutions. Hopefully this clears up the confusion on this topic.
除了循环之外,yield 和 block 还有更多内容。
系列枚举可枚举有一系列你可以用枚举做的事情,比如询问如果某个陈述对于组中的任何成员都成立,或者对于所有成员都成立,或者搜索满足特定条件的任何或所有成员。
块对于变量范围也很有用。 它不仅仅是方便,还可以帮助实现良好的设计。 例如,代码
确保文件流在您完成后关闭,即使发生异常,并且一旦您完成它,变量就超出范围。
随便谷歌一下,并没有找到一篇关于 ruby 中的块和收益的好博客文章。 我不知道为什么。
对评论的回应:
我怀疑它被关闭是因为块结束,而不是因为变量超出范围。
我的理解是,当指向对象的最后一个变量超出范围时,除了该对象有资格进行垃圾回收之外,不会发生任何特殊情况。 但我不知道如何确认这一点。
我可以证明文件对象在垃圾收集之前就被关闭了,这通常不会立即发生。 在下面的示例中,您可以看到文件对象在第二个
puts
语句中被关闭,但尚未被垃圾回收。There's more to yield and blocks than mere looping.
The series Enumerating enumerable has a series of things you can do with enumerations, such as asking if a statement is true for any member of a group, or if it's true for all the members, or searching for any or all members meeting a certain condition.
Blocks are also useful for variable scope. Rather than merely being convenient, it can help with good design. For example, the code
ensures that the file stream is closed when you're finished with it, even if an exception occurs, and that the variable is out of scope once you're finished with it.
A casual google didn't come up with a good blog post about blocks and yields in ruby. I don't know why.
Response to comment:
I suspect it gets closed because of the block ending, not because the variable goes out of scope.
My understanding is that nothing special happens when the last variable pointing to an object goes out of scope, apart from that object being eligible for garbage collection. I don't know how to confirm this, though.
I can show that the file object gets closed before it gets garbage collected, which usually doesn't happen immediately. In the following example, you can see that a file object is closed in the second
puts
statement, but it hasn't been garbage collected.我认为
yield
语句源自 CLU语言。 我一直想知道 Tron 中的角色是否也以 CLU 命名......I think the
yield
statement originated from the CLU language. I always wonder if the character from Tron was named after CLU too....我认为 'coroutine' 是您正在寻找的关键字。
例如 http://en.wikipedia.org/wiki/Yield
计算和信息科学领域的产出:
I think 'coroutine' is the keyword you're looking for.
E.g. http://en.wikipedia.org/wiki/Yield
Yield in computing and information science: