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等等,所以我想要一些通用的东西。
如果你能让它适用于地图(使用相同的名字build,而不是build2或buildMap)
发布于 2014-07-07 08:50:47
这将不适用于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))发布于 2015-06-18 08:24:42
塞尼娅的解决方案很棒。不幸的是,正如他所提到的,这对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 )
https://stackoverflow.com/questions/24605382
复制相似问题