我很难理解为什么Scala编译器对此函数定义不满意:
def trimNonWordCharacters[T <: Iterable[String]](items: T): T =
items map { _.replaceAll("\\W", "") }
以下是REPL输出:
scala> def trimNonWordCharacters[T <: Iterable[String]](items: T): T =
items map { _.replaceAll("\\W", "") }
<console>:5: error: type mismatch;
found : Iterable[java.lang.String]
required: T
def trimNonWordCharacters[T <: Iterable[String]](items: T): T = items map { _.replaceAll("\\W", "") }
目标是传递Iterable的任何实现并获得相同类型的退出。这可能吗?
答案 0 :(得分:14)
map
上的Iterable
方法会返回Iterable
,因此即使T
是Iterable
的子类,它的map
方法也会返回Iterable
。
为了更好地打字,你必须这样写:
import scala.collection.IterableLike
def trimNonWordCharacters[T <: Iterable[String]](items: T with IterableLike[String, T]): T =
items map { _.replaceAll("\\W", "") }
然而,这也无效,因为没有信息让T
上的地图生成另一个T
。例如,将BitSet
映射到String
不会产生BitSet
。所以我们需要其他东西:教导如何从T
构建T
,其中映射元素的类型为String
。像这样:
import scala.collection.IterableLike
import scala.collection.generic.CanBuildFrom
def trimNonWordCharacters[T <: Iterable[String]]
(items: T with IterableLike[String, T])
(implicit cbf: CanBuildFrom[T, String, T]): T =
items map { _.replaceAll("\\W", "") }
答案 1 :(得分:0)
[输入为答案而不是评论,因为评论中的代码格式不正确]
@Daniel,谢谢你的解释,我也发现它很有用。由于Iterable来自IterableLike,以下似乎也有效,并且稍微紧凑:
import scala.collection.IterableLike
import scala.collection.generic.CanBuildFrom
def trimNonWordCharacters[T <: IterableLike[String, T]]
(items: T)
(implicit cbf: CanBuildFrom[T, String, T]): T =
items map { _.replaceAll("\\W", "") }