当用作回调时,Ruby 块中的“return”和“break”是不是无用?
Posted
技术标签:
【中文标题】当用作回调时,Ruby 块中的“return”和“break”是不是无用?【英文标题】:Are `return` and `break` useless inside a Ruby block when used as a callback?当用作回调时,Ruby 块中的“return”和“break”是否无用? 【发布时间】:2011-06-09 18:54:44 【问题描述】:在 Rails 中,blocks can be used as callbacks,例如:
class User < ActiveRecord::Base
validates_presence_of :login, :email
before_create |user| user.name = user.login.capitalize
if user.name.blank?
end
当这样使用块时,break
和 return
有什么用吗?我问是因为通常在一个块中,break
将跳出循环,return
将从封闭方法返回。但是在回调上下文中,我无法理解这意味着什么。
The Ruby Programming Language 建议 return
可能会导致 LocalJumpError
但我无法在 Rails 回调中重现这一点。
编辑:使用下面的代码,我希望有一个LocalJumpError
,但return
所做的只是停止其余的回调执行。
class User < ActiveRecord::Base
validates_presence_of :login, :email
before_create do |user|
return
user.name = user.login.capitalize
end
【问题讨论】:
【参考方案1】:其实挺有意思的……
当您在 Rails 3 中使用 before_create 时,我们会将您提供给我们的块或 lambda 转换为方法。然后我们使用当前的 ActiveRecord 对象调用该方法,以向后兼容旧的 Rails 方法。
结果,下面相当于你的sn-p:
class User < ActiveRecord::Base
validates_presence_of :login, :email
before_create do
self.name = login.capitalize if name.blank?
end
end
由于这种行为,您可以从块中调用 return,它的行为与普通方法中的 return 相同(因为它是普通方法)。
一般来说,块中的continue
从块中“返回”。
普通方块的具体行为是:
当您调用continue
时,您将跳过该块的其余部分,并将控制权返回给调用该块的方法。
当您调用 break
时,您将跳过该块的其余部分,并立即从调用该块的方法返回。
您可以在普通迭代器中看到这种行为:
value = [1,2,3,4].each do |i|
continue if i == 2
puts i
end
在这种情况下,value
将是 [1,2,3,4]
,each
方法的正常返回值,输出将是:
1
3
4
在break的情况下:
value = [1,2,3,4].each do |i|
break if i == 2
puts i
end
在这种情况下,value
将是nil
,因为break
也立即从each
方法返回。您可以使用break n
强制返回具有特定值的返回值,这将使value
与n
相同。上述情况下的输出将是:
1
重要的是,continue
和 break
不仅仅适用于迭代器,尽管它们的语义被设计成在迭代器的情况下表现得与 C 中的等价物一样。
【讨论】:
谢谢,这真的很有意义。【参考方案2】:return
在 Ruby 块中的操作取决于该块是使用 Proc.new
还是 lambda
构造的。
我建议您阅读其他 Stack Overflow 问题中评分最高的答案:When to use lambda, when to use Proc.new?
在这种情况下,块具有使用Proc.new
创建的块的属性。
在这种回调的上下文中调用 return
只有在这也有意义的情况下才有意义(显然没有):
class Foo
return "bar"
end
【讨论】:
@Andy - 谢谢。在这种情况下,块是一个 Proc,但它不是用Proc.new
或 lambda
构造的——它是作为一个块传入的。还是你在before_create
里面说的?
@Andy - 阅读了那个答案,问题是在这种情况下很明显return
将从包含方法返回。但是,如果它在类定义中,那么包含方法是什么?
在这种情况下,回调基本上是一个Proc.new
创建的块。
那么如果我从那个街区回来,我会从什么地方回来?
您正在退出创建它的上下文。如果在不同的上下文中执行,这会导致 LocalJumpError
。以上是关于当用作回调时,Ruby 块中的“return”和“break”是不是无用?的主要内容,如果未能解决你的问题,请参考以下文章
Nodejs:catch块中的回调函数在try-catch中返回未定义的参数
Java中,finally在try语句块中的return前执行还是后执行
Java中,finally在try语句块中的return前执行还是后执行
当对象的方法之一用作其自身属性的回调时,如何调用对象的析构函数?
iOS 中的 iBeacons - 没有来自实际 BLE 设备的回调,但是当另一个 iOS 设备用作广播器时会调用 didRangeBeacons