从范围初始化scala BitSet

时间:2011-06-16 04:05:29

标签: scala

我想初始化一个scala BitSet来包含从1到N的整数。以下内容可行,但我正在寻找更好的解决方案:

var s = BitSet.empty ++ (1 to n)

我希望我可以这样做:

var s:BitSet = (1 to n).toSet

...但这会导致错误:

error: polymorphic expression cannot be instantiated to expected type;
  found   : [B >: Int]scala.collection.immutable.Set[B]
  required: scala.collection.immutable.BitSet

我错过了一些明显的东西吗?

2 个答案:

答案 0 :(得分:13)

那是breakOut的用途:

val s: BitSet = (1 to n).map(identity)(breakOut)

请参阅this question以了解breakOut的内部工作情况。

另一种解决方案是使用BitSet的构造函数:

val s = BitSet((1 to n): _*)

: _*告诉编译器您希望将Range用作重复参数。

因为breakOut看起来很丑,你可以使用pimp-my-library模式生成更好看的代码(如here所述):

val s = (1 to n).to[BitSet]

答案 1 :(得分:3)

深入研究Scala源代码,toBitSet的定义在TraversibleOnce.scala中:

/** Converts this $coll to a set.
 *  $willNotTerminateInf
 *  @return      a set containing all elements of this $coll.
 */
def toSet[B >: A]: immutable.Set[B] = immutable.Set() ++ self

所以,有趣的是,toSet的Scala实现基本上只是在普通Set的情况下在幕后做第一个解决方案。如果你真的非常喜欢你为BitSet的情况建议的第二种语法,那么你可以使用隐式类型转换来推销自己的语法:

class BitSetConvertible(t: TraversableOnce[Int]) {
  def toBitSet = BitSet.empty ++ t
}

implicit def asBitSetConvertible(t: TraversableOnce[Int]) = new BitSetConvertible(t)

有了这个,您现在可以发表如下声明:

val s = 1 to 10 toBitSet