Ruby与计算机科学相关的屈服特征

hbw*_*hbw 49 ruby functional-programming yield

我最近发现了Ruby的块和屈服特征,我想知道:这在计算机科学理论方面适合哪些方面?它是一种函数式编程技术,还是更具体的?

Chu*_*uck 104

Ruby yield不是像C#和Python那样的迭代器.yield一旦你理解了块如何在Ruby中工作,它本身就是一个非常简单的概念.

是的,块是一种函数式编程功能,即使Ruby不是一种功能性语言.实际上,Ruby使用该方法lambda来创建块对象,这是从Lisp的语法中借用来创建匿名函数 - 这就是块.从计算机科学的角度来看,Ruby的块(以及Lisp的lambda函数)是闭包.在Ruby中,方法通常只占用一个块.(你可以传递更多,但它很尴尬.)

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

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
Run Code Online (Sandbox Code Playgroud)

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

with_log do
  a = 5
  other_num = gets.to_i
  @my_var = a + other_num
end
Run Code Online (Sandbox Code Playgroud)

它会打印出最终分配给它的价值@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]
Run Code Online (Sandbox Code Playgroud)

正如Andrew所说,它也常用于打开文件和许多其他地方.基本上,只要你有一个可以使用某些自定义逻辑的标准函数(比如对数组进行排序或处理文件),你就会使用一个块.还有其他一些用途,但这个答案已经很久了,我担心它会对体质较弱的读者造成心脏病发作.希望这可以消除对这个主题的困惑.

  • 谢谢,这更有意义,而且它与我迄今为止学到的关于块的内容有很多联系. (3认同)
  • 很好的解释. (2认同)
  • 简而言之,这只是一个穷人的关闭. (2认同)

And*_*imm 6

屈服和阻塞不仅仅是循环.

Enumerating enumerable系列包含一系列您可以对枚举执行的操作,例如询问某个组的任何成员的语句是否为true,或者所有成员是否为true,或者搜索满足某个条件的任何或所有成员.

块对于可变范围也很有用.它不仅仅是方便,而且有助于良好的设计.例如,代码

File.open("filename", "w") do |f|
  f.puts "text"
end
Run Code Online (Sandbox Code Playgroud)

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

一个随意的谷歌没有提出关于红宝石块和收益率的好博客文章.我不知道为什么.

回复评论:

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

我的理解是,当指向对象的最后一个变量超出范围时,除了该对象符合垃圾收集条件之外,没有什么特别的事情发生.不过,我不知道如何证实这一点.

我可以证明文件对象在收集垃圾之前就已关闭,这通常不会立即发生.在下面的示例中,您可以看到文件对象在第二个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
Run Code Online (Sandbox Code Playgroud)

  • @aidan使用块调用`File#open`方法,一旦块完成,将关闭创建的文件句柄. (3认同)