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)
答案 0 :(得分:4)
这不适用于String
或Map
。此代码也需要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的解决方案很棒。不幸的是,他提到这不会对Map
和String
起作用。
这是另一种选择(基于他的解决方案),它确实:
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[_]]
。作为交换,您可以指定所需的任何目标集合,而不管类型参数的数量(例如Map
和String
)。
另外,如果您选择:
,您仍然可以完全明确(与使用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
,如您所要求的那样)