使用自定义CanBuildFrom和Builder获取映射函数以在Scala中工作
我让一个生成器用Int生成一个字符串:使用自定义CanBuildFrom和Builder获取映射函数以在Scala中工作,scala,map,Scala,Map,我让一个生成器用Int生成一个字符串: class MyBuilder extends LazyBuilder[Int, String] { def result: String = "value: " + Int.toString } 这可以通过实施来实现: class IntToStringCanBuildFrom extends CanBuildFrom[Set[Int], Int, String] { def apply(from: Set[Int]
class MyBuilder extends LazyBuilder[Int, String]
{
def result: String = "value: " + Int.toString
}
这可以通过实施来实现:
class IntToStringCanBuildFrom extends CanBuildFrom[Set[Int], Int, String]
{
def apply(from: Set[Int]) = this.apply()
def apply() : MyBuilder = new MyBuilder
}
我想在下面的例子中使用它:
val list = List(1, 2, 3)
val result = list.map(2*)(new IntToStringCanBuildFrom)
但我得到一个编译错误:
- type mismatch; found : Test.IntToStringCanBuildFrom required:
scala.collection.generic.CanBuildFrom[List[Int],Int,?]
我到底做错了什么?如何做到这一点?显然,它不喜欢我的CanBuildFrom实现有一个字符串类型的param,但我认为这应该是实现这一点的方法。要做到这一点,代码中有几点需要更改:
- 首先,您可以将
定义为用于CanBuildFrom
设置为输入,但您给它一个将[Int]
(它不是列表[Int]
!)。因此,它应该是,例如,集
。因为CanBuildFrom[Seq[Int],Int,String]
是一个列表
,所以它可以工作序列
- 然后,您的懒惰构建器需要对它接收到的元素进行实际操作。它公开了一个
,其中包含添加到其中的所有内容。让我们只打印它的内容:受保护的var parts:ListBuffer[TraversableOnce[Int]]
然后,调用时,class MyBuilder extends LazyBuilder[Int, String] { def result: String = "value: " + parts.flatten.mkString(",") }
可以创建该生成器:CanBuildFrom
class IntSeqToStringCanBuildFrom extends CanBuildFrom[Seq[Int], Int, String] { def apply(from: Seq[Int]): Builder[Int, String] = apply() def apply(): Builder[Int, String] = new MyBuilder }
- 最后,您可以直接使用它:
或通过隐式范围间接:scala> val list = List(1, 2, 3) list: List[Int] = List(1, 2, 3) scala> val result = list.map(2 * _)(new IntSeqToStringCanBuildFrom) result: String = value: 2,4,6
scala> implicit val intSeqCanBuildFrom = new IntSeqToStringCanBuildFrom intSeqCanBuildFrom: IntSeqToStringCanBuildFrom = IntSeqToStringCanBuildFrom@52cc537d scala> val result: String = list.map(2 * _) result: String = value: 2,4,6
Int
都有一个String
,因此您希望,例如,一个Seq[String]
作为输出?但是,list.map(s=>”值:“+s)
就足够了,不需要CanBuildFrom
。你想用你的CanBuildFrom
生成什么样的集合类型?是的,我知道这不是一个很好的例子,这不是一个真实的情况,我只是想了解这个问题。我最初认为它的工作方式是为每个元素调用构建器,但正如您所说,它将获得整个parts ListBuffer,我必须从中生成我自己的Seq。现在我有了一个类MyBuilder extensed LazyBuilder[Int,Seq[String]]
和一个类IntToStringCanBuildFrom extensed CanBuildFrom[Seq[Int],Int,Seq[String]]
,这似乎满足了我的需求。