更简洁的替代breakOut

时间:2014-07-07 07:45:05

标签: scala

breakOut很好,但过于冗长:

List(1, 2, 3).map{i => (i * 2, i / 2.0, i.toString)}(breakOut) : Array[(Int, Double, String)]

我不想指定元素类型。我想要这样的东西:

 List(1, 2, 3).map{i => (i * 2, i / 2.0, i.toString)}(build[Array])

我可以轻松地编写buildArray,但是我需要buildSet,buildList等等。所以我想要一些通用的东西。

额外点(;-))如果你可以使它适用于Map(使用相同的名称build,而不是build2或buildMap)

2 个答案:

答案 0 :(得分:4)

这不适用于StringMap。此代码也需要scala.language.higherKinds

import collection.generic.CanBuildFrom
import collection.breakOut

class Build[To[_]]

def build[To[_]] = new Build[To]

implicit def buildToCbf[From, T, To[_]](b: Build[To])
                                       (implicit cbf: CanBuildFrom[Nothing,T,To[T]]): CanBuildFrom[From,T,To[T]] =
  collection.breakOut

List(1, 2, 3).map{i => (i * 2, i / 2.0, i.toString)}(build[Array])
//res0: Array[(Int, Double, String)] = Array((2,0.5,1), (4,1.0,2), (6,1.5,3))

答案 1 :(得分:1)

Senia的解决方案很棒。不幸的是,他提到这不会对MapString起作用。 这是另一种选择(基于他的解决方案),它确实:

import collection.generic.CanBuildFrom
import collection.breakOut

class Build[To]

def build[TargetSuperType] = new Build[TargetSuperType]

implicit def buildToCbf[From, T, TargetSuperType, To<:TargetSuperType](b: Build[TargetSuperType])
                                       (implicit cbf: CanBuildFrom[Nothing,T,To]): CanBuildFrom[From,T,To] =
  collection.breakOut

List(1, 2, 3).map{i => (i * 2, i / 2.0, i.toString)}(build[Array[_]])
//res0: Array[(Int, Double, String)] = Array((2,0.5,1), (4,1.0,2), (6,1.5,3))

List(1, 2, 3).map{i => (i * 2, i.toString)}(build[Map[_,_]])
//res1: scala.collection.immutable.Map[Int,String] = Map(2 -> 1, 4 -> 2, 6 -> 3)

List('a', 'b', 'c').map(_.toUpper)(build[String])
//res2: String = ABC

这更加冗长,因为现在你不仅仅build[Array],而是build[Array[_]]。作为交换,您可以指定所需的任何目标集合,而不管类型参数的数量(例如MapString)。

另外,如果您选择:

,您仍然可以完全明确(​​与使用breakOut时类似)
scala> List(1, 2, 3).map{i => (i * 2, i / 2.0, i.toString)}(build[Array[(Int, Double, String)]])
res3: Array[(Int, Double, String)] = Array((2,0.5,1), (4,1.0,2), (6,1.5,3))

具有相同语法的所有内容(换句话说,使用相同的名称build,如您所要求的那样)