加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

Ruby enumerables不保持同一个类

发布时间:2020-12-17 03:54:32 所属栏目:百科 来源:网络整理
导读:我有一个代表集合的类.我将Enumerable模块包含在其中并定义了方法#each,以便我获得所有方法. 但问题是Enumerable的方法不能保持同一个类.所以,例如,如果我的类名为Collection,如果我做Collection #select,我希望结果的类也是Collection(而不是Array).有没有
我有一个代表集合的类.我将Enumerable模块包含在其中并定义了方法#each,以便我获得所有方法.

但问题是Enumerable的方法不能保持同一个类.所以,例如,如果我的类名为Collection,如果我做Collection #select,我希望结果的类也是Collection(而不是Array).有没有办法如何实现这一目标?

解决方法

不幸的是,Ruby的Collection Operations不是类型保留的.每个集合操作始终返回一个Array.

对于像集合或树的集合,这只是令人讨厌,因为您需要始终将它们转换回您想要的类型.但是例如对于所有素数的无限懒惰流,这是灾难性的:你的程序将挂起或耗尽内存试图构造一个无限大的数组.

大多数Collection API要么消除重复的代码,要么保留类型,但不能同时保留两者.例如. .NET的Collection API主要消除了重复的代码,但它总是返回相同的类型:IEnumerable(相当于Ruby的Enumerator). Smalltalk的Collection API是类型保留的,但它通过复制每个Collection类型中的所有Collection Operations来实现这一点.

唯一保留类型但却消除重复的Collection API是Scala.它通过引入Collection Builders的新概念来实现这一点,Collection Builders知道如何有效地构建特定类型的Collection.收集操作是根据Collection Builders实现的,只有Collection Builders需要复制……但这些都是特定于每个Collection的.

如果你想在Ruby中保留类型保存的Collection操作,你需要复制你自己的Collection中的所有Collection Operations(这将仅限于你自己的代码),或者重新设计整个Collection API以使用Builders(这需要重大的重新设计)不仅是您自己的代码,还包括现有的集合,包括所有第三方集合.

很明显,第二种方法至少是不切实际的,如果不是不可能的话.第一种方法也存在问题:收集操作有望返回数组,违反了预期可能会破坏其他人的代码!

您可以采用类似于Ruby 2.0的惰性集合操作的方法:您可以向API添加一个新方法preserve_type,它返回一个具有类型保留Collection Operations的代理对象.这样,代码中明确标出了对标准API的偏离:

c.select …               # always returns an Array

c.preserve_type.select … # returns whatever the type of c is

就像是:

class Hash
  def preserve_type
    TypePreservingHash.new(self)
  end
end

class TypePreservingHash
  def initialize(original)
    @original = original
  end

  def map(*args,&block)
    Hash[@original.map(*args,&block)
    # You may want to do something more efficient
  end
end

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读