返回 procs、lambdas 和 blocks 中的语句

Posted

技术标签:

【中文标题】返回 procs、lambdas 和 blocks 中的语句【英文标题】:Return statements inside procs, lambdas, and blocks 【发布时间】:2013-03-11 20:54:34 【问题描述】:

我很难理解 return 如何在块、procs 和 lambdas 中工作。

例如,在以下情况下,为什么batman_ironman_proc 工作,而batman_yield 抛出错误?

def batman_ironman_proc
  victor = Proc.new  return "Batman will win!" 
  victor.call
  "Iron Man will win!"
end

def batman_yield
    yield
    "Iron man will win!"
end

victor = Proc.new  return "Batman will win!" 

puts batman_ironman_proc 
#batman_yield(&victor) === This code throws an error.

【问题讨论】:

Using 'return' in a Ruby block 的可能重复项 这里:***.com/questions/1435743/… 我知道你正在从 codeacademy 学习这个。我也有同样的疑问。这是一个不错的入门教程,但你必须在谷歌上搜索很多才能理解教程。 【参考方案1】:

正如链接问题中的one answer 所示:

return 关键字总是从当前上下文中的方法或 lambda 返回。在块中,它将从 定义 闭包的方法返回。它不能从 调用 方法或 lambda 中返回。

您的第一个示例是成功的,因为您在想要返回的同一个函数中定义了victor,因此return 在这种情况下是合法的。在您的第二个示例中,victor 是在顶层定义的。那么,return 的效果将不是batman_yield(调用方法)返回,而是 [如果它有效] 从顶层本身返回(其中Proc 已定义)。

澄清:虽然您可以访问块的返回值(即“块中评估的最后一个表达式的值作为产量的值传递回方法” - 如根据您的评论),由于上述原因,您不能使用 return 关键字。示例:

def batman_yield
    value = yield
    return value
    "Iron man will win!"
end

victor = Proc.new  return "Batman will win!" 
victor2 = Proc.new  "Batman will win!" 

#batman_yield(&victor) === This code throws an error.
puts batman_yield(&victor2) # This code works fine.

【讨论】:

鉴于这种情况,find等接受逻辑测试块的方法如何使用这些逻辑测试的结果? (例如:[1,2,3,4,8,10].find |num| num*num>24) @user1419674 查看更新后的答案。与您的示例代码没有使用return 的方式相同,您也不必使用它来访问块的评估。您可以只使用来自call 的返回值,直接使用它(如在我的示例代码中)或将其分配给变量(例如:value = block.call 这对我来说很奇怪,但我相信这个链接可以回答这个问题。 [链接]ruby-doc.org/docs/ProgrammingRuby/html/tut_containers.html其实说yield可以提供返回值。让我感到奇怪的是,在这种情况下,显式返回和隐式返回似乎会在块内产生不同的结果。 这里是链接的相关摘录:“块也可以将值返回给方法。块中计算的最后一个表达式的值作为yield。这就是类 Array 使用的 find 方法的工作原理。[find 方法实际上是在模块 Enumerable 中定义的,它被混合到类 Array 中。]它的实现如下所示。" @user1419674 感谢您指出yield 可以返回一个值,我更新了答案。关于“奇怪”,我对这个功能也有这种感觉,但至少规范是明确的:return 关键字是相对于 定义 上下文,而不是 调用 i> 一个。【参考方案2】:

我来自 C 背景,我将解释它的方式是,当您调用一个函数时,您会设置一个返回指令号和一个将存储返回值的寄存器。在 proc 和 block 的情况下,没有设置返回指令,因为它们是在同一范围内内联或调用的,但它们仍然可以返回返回值,因为它们是独立的功能。因此,如果没有设置返回指令,proc/block 会给我们一个 LocalJumpError,而如果我们只想返回一个值,那很好。

【讨论】:

以上是关于返回 procs、lambdas 和 blocks 中的语句的主要内容,如果未能解决你的问题,请参考以下文章

proc、Proc.new、lambda 和 stabby lambda 之间的速度差异

什么是 procs 和 lambdas?请提供实际示例[重复]

ruby中proc和lambda的return区别

Ruby 中的 proc 和 lambda 有啥区别?

为啥 Enumerable#detect 需要 Proc/lambda?

iOS开发学习48 OC的lambda block