tl;dr
import scala.collection.SeqLike
import scala.collection.generic.CanBuildFrom
implicit class Seq_[A, Repr,
S : ({type L[X] = X => SeqLike[A, Repr]})#L](seq: S) {
def myApply[B >: A, That](f: A => B, ith: Int)
(implicit bf: CanBuildFrom[Repr, B, That]): That =
seq.updated(ith - 1, f(seq(ith - 1)))
}
讨论
一个简单的近似:
implicit class Seq_[A](seq: Seq[A]) {
def myApply(f: A => A, ith: Int): Seq[A] =
seq.updated(ith - 1, f(seq(ith - 1)))
}
示例用法:
scala> (1 to 3).toList.myApply(_ + 10, ith = 2)
res: Seq[Int] = List(1, 12, 3)
尝试的实际解决方案:
implicit class Seq_[A, Repr <: SeqLike[A, Repr]](seq: Repr) {
def myApply[B >: A, That](f: A => B, ith: Int)
(implicit bf: CanBuildFrom[Repr, B, That]): That =
seq.updated(ith - 1, f(seq(ith - 1)))
}
不幸的是,隐式不起作用。我不知道为什么。
scala> Seq_[Int, List[Int]]((1 to 3).toList).myApply(_ + 10, ith = 2)
res: List[Int] = List(1, 12, 3)
scala> Seq_[Int, List[Int]]((1 to 3).toList).myApply(_.toString + "*", ith = 2)
res: List[Any] = List(1, 2*, 3)
编辑:修复它!
implicit class Seq_[A, Repr](seq: SeqLike[A, Repr]) {
def myApply[B >: A, That](f: A => B, ith: Int)
(implicit bf: CanBuildFrom[Repr, B, That]): That =
seq.updated(ith - 1, f(seq(ith - 1)))
}
例子:
scala> (1 to 3).toList.myApply(_ + 10, ith = 2)
res: List[Int] = List(1, 12, 3)
scala> (1 to 3).toVector.myApply(Math.pow(2, _), ith = 3)
res: scala.collection.immutable.Vector[AnyVal] = Vector(1, 2, 8.0)
但我刚刚意识到你也希望它适用于 Array,而不是 SeqLike,所以让我再想一想......
啊,Predef 有一个从Array 到ArrayOps 的隐式转换,这是SeqLike 的子类型,所以我们只需要使用视图绑定即可。
implicit class Seq_[A, Repr <% SeqLike[A, Repr]](seq: Repr) {
def myApply[B >: A, That](f: A => B, ith: Int)
(implicit bf: CanBuildFrom[Repr, B, That]): That =
seq.updated(ith - 1, f(seq(ith - 1)))
}
最后我们有了正确的行为:
scala> (1 to 3).toList.myApply(_ + 10, ith = 2)
res: List[Int] = List(1, 12, 3)
scala> (1 to 3).toArray.myApply(Math.pow(2, _), ith = 3)
res: Array[AnyVal] = Array(1, 2, 8.0)
再次编辑 - samthebest 通知我不推荐使用视图边界,因此使用 this guide 我们可以将其替换为外观非常难看的上下文边界。
implicit class Seq_[A, Repr,
S : ({type L[X] = X => SeqLike[A, Repr]})#L](seq: S) {
def myApply[B >: A, That](f: A => B, ith: Int)
(implicit bf: CanBuildFrom[Repr, B, That]): That =
seq.updated(ith - 1, f(seq(ith - 1)))
}