2

我有一个生成器从一个 Int 中创建一个字符串:

  class MyBuilder extends LazyBuilder[Int, String]
  {
    def result: String = "value: " + Int.toString
  }

而这个 CanBuildFrom 实现:

  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 实现具有 String 类型参数的事实,但我认为这应该是这样做的方法。

4

1 回答 1

3

为此,您的代码中有几处需要更改:

  • 首先,你CanBuildFrom被定义为Set[Int]作为输入工作,但你给它一个List[Int](这不是一个Set!)。所以它应该是,例如,CanBuildFrom[Seq[Int], Int, String]。由于 aList是 a Seq,它会工作。

  • 然后,您的惰性构建器需要对其接收到的元素进行实际操作。它公开了一个protected var parts: ListBuffer[TraversableOnce[Int]]包含添加到其中的所有内容的 a。让我们打印它的内容:

    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
    
于 2013-07-27T14:07:03.163 回答