ruby - 为什么有人会扔出一个非符号呢?

标签 ruby

Ruby 的 throw 语句接受任何 Object,这意味着下面的任何一个都是合法的。

throw BasicObject
throw 123456.78
throw "wow"
throw :doge

但是,根据我的理解,我选择抛出 Symbol 有两个原因。

  1. 必须捕获与抛出的完全相同的对象。这意味着执行 catch "wow" 将导致 UncaughtThrowError。使用 Symbol 时这不是问题。
  2. catch 后无法引用抛出的对象。要指定返回值,可以将其输入为第二个参数: throw :doge, "wow" 在我看来,这会破坏抛出自定义 Object 的全部意义..

此外,令人困惑的是,在 ruby 1.9 之前,throw 的(第一个)参数过去仅限于 Symbols。这是否意味着有人必须抛出非符号,并且 ruby​​ 必须更改其实现以允许此类用例?或者是其他什么......比如节省类型检查的执行时间。

此时,我唯一能想象到的与 Symbol 不同的是 Fixnum,但这就是更改的原因吗?请赐教。

最佳答案

假设您正在使用一些您不关心其内部结构的库。如果该库使用带有某个符号(或任何其他常见对象)的 throw 方法,而该符号(或任何其他常见对象)意外地与您要抛出的符号(或对象)相同,该怎么办? - 在你自己的代码中?这会导致不必要的交互。另一方面,如果创建自定义对象并抛出它,则不必关心此类问题。特别是如果您仅将其定义为局部变量,那么它是安全的。如果将其定义为常量,那么它会相对安全(危险在于其他库不小心在同一 namespace 中使用了相同的常量名称)。

带有 block 参数的

catch 创建一个 Object 实例,并将其分配为 block 变量,这使其安全。

当我使用throw时,我通常不能使用 block 变量形式,因为大多数时候,我throwcatch在不同的地方方法。因此,我创建了一个 Object 实例,并将其指定为私有(private)常量,这使得它相对安全。

class SomeClass
  Foo = Object.new
  private_constant :Foo

  def some_method
    ...
    catch(Foo){... another_method ...}
    ...
  end
  def another_method
    ...
    throw(Foo)
    ...
  end
end

关于ruby - 为什么有人会扔出一个非符号呢?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35450221/

相关文章:

ruby-on-rails - Ruby:你能确定一个对象是否正在调用其方法之一吗?

ruby - 数组求幂

ruby-on-rails - Active Record 中的“或”运算符?

ruby - 理解 Ruby 中单例方法如何工作的问题

ruby-on-rails - 在 Ruby 中将排序实现为类方法

ruby - 如何杀死一个进程及其所有子进程

ruby-on-rails - Rails 5 - 如何对 has_many 关联列表进行排序?

ruby - Redis:我应该将 IP 转换为整数吗?

mysql - 最好的方法是什么......考虑性能

mysql - 在给定 sql 查询的情况下转换 Rails 中的复杂查询