我试图找出如何编写适用于任何Traversable[_]
的函数交换函数,给定集合和交换索引。我想出了以下内容:
def swap[A, CC <% Traversable[A]](xs: CC, i: Int, j: Int): Traversable[A] = {
xs.slice(0, i) ++
xs.slice(j, j+1) ++
xs.slice(i+1, j) ++
xs.slice(i, i+1) ++
xs.slice(j+1, xs.size)
}
swap(List(1,2,3,4,5), 0, 4) // => List(5,2,3,4,1)
我想知道如何将它变成Traversable的隐式扩展,让我可以用List(1,2,3,4,5).swap(0, 4)
来调用它。我能得到的最接近的是:
import language.implicitConversions
class RichTraversable[A, B <% Traversable[A]](xs: B) {
def swap(i: Int, j: Int): Traversable[A] = {
xs.slice(0, i) ++
xs.slice(j, j+1) ++
xs.slice(i+1, j) ++
xs.slice(i, i+1) ++
xs.slice(j+1, xs.size)
}
}
implicit def richTraversable[A, B <% Traversable[A]](ys: B)(implicit b: Traversable[A])
= new RichTraversable[A, B](ys)
不幸的是,这不是它。调用List(1,2,3,4,5).swap(0, 4)
会导致以下错误:
错误:List [Int]中没有隐式视图=&gt;横越[A]
我觉得我必须遗漏某些东西,或者使问题过于复杂。有谁知道这应该如何构建?
注意:这纯粹是学术性的,不会以任何方式在生产环境中使用。我正试图更好地处理Scala的类型系统和界限。
答案 0 :(得分:4)
如果您使用的是Scala 2.10:
import scala.collection.generic.CanBuildFrom
import scala.collection.TraversableLike
implicit class TraversableWithSwap[A, Repr <: Traversable[A]](val xs: TraversableLike[A, Repr]) extends AnyVal {
def swap[That](i: Int, j: Int)(implicit bf: CanBuildFrom[Repr, A, That]): That = {
val builder = bf(xs.asInstanceOf[Repr])
builder.sizeHint(xs)
builder ++= xs.take(i)
builder ++= xs.slice(j, j + 1)
builder ++= xs.slice(i + 1, j)
builder ++= xs.slice(i, i + 1)
builder ++= xs.drop(j + 1)
builder.result
}
}
(AnyVal
事物将其转换为值类,这意味着编译器会将其重写为静态函数,以避免在运行时实际执行包装。)
如果使用的是早期版本,请删除extends AnyVal
并使用隐式转换功能代替implicit class
:
implicit def toTraversableWithSwap[A, Repr <: Traversable[A]](xs: TraversableLike[A, Repr]) = new TraversableWithSwap(xs)
使用它:
scala> Vector(1,2,3,4,5,6,7,8,9).swap(2,5)
res0: scala.collection.immutable.Vector[Int] = Vector(1, 2, 6, 4, 5, 3, 7, 8, 9)
请注意,为所有Traversable
定义此函数实际上没有意义,因为某些可遍历(如Set
,Map
等)是无序的,因此交换两个元素是无意义的。您可能实际上想要为所有Seq
或其他东西定义它。
另外:我们也可以同意将其称为“增强我的库”吗?