我想初始化一个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
我错过了一些明显的东西吗?
答案 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