在这个参数化的Scala函数中,为什么需要强制转换?
发布时间:2020-12-16 09:59:34 所属栏目:安全 来源:网络整理
导读:在这个参数化函数中,为什么我需要演员?我怎么能摆脱它呢? /** Filters `xs` to have only every nth element. */def everyNth[A % Iterable[B],B](xs: A,n: Int,offset: Int = 0): A = (xs.zipWithIndex collect { case (x,i) if (i - offset) % n == 0 =
在这个参数化函数中,为什么我需要演员?我怎么能摆脱它呢?
/** Filters `xs` to have only every nth element. */ def everyNth[A <% Iterable[B],B](xs: A,n: Int,offset: Int = 0): A = (xs.zipWithIndex collect { case (x,i) if (i - offset) % n == 0 => x }).asInstanceOf[A] 如果我最后没有演员,我会收到以下错误消息: type mismatch; found : Iterable[B] required: A 这个函数(使用强制转换)适用于我尝试过的所有情况,我知道在REPL中输入类似下面的内容,Scala能够在不在参数化函数的上下文中正确推断结果类型: scala> val a: Stream[Int] = (Stream.from(0).zipWithIndex collect { case (x,i) if (i + 3) % 5 == 0 => x }) a: Stream[Int] = Stream(2,?) scala> a take 10 force res20: scala.collection.immutable.Stream[Int] = Stream(2,7,12,17,22,27,32,37,42,47) 请解释! 解决方法
根据评论中的一些建议,我查看了CanBuildFrom,这就是我想出的:
import scala.collection.IterableLike import scala.collection.generic.CanBuildFrom /** Filters `xs` to have only every nth element. */ def everyNth[A,It <: Iterable[A]] (xs: It with IterableLike[A,It],offset: Int = 0) (implicit bf: CanBuildFrom[It,A,It]): It = { val retval = bf() retval ++= xs.zipWithIndex collect { case (x,i) if (i - offset) % n == 0 => x } retval.result } 是的,它的工作原理! 而且没有演员阵容.因此,它甚至适用于Ranges. 然而,不得不从一个空的retval开始,然后使用“=”填充它似乎有点不优雅,所以如果有人有一个更优雅的解决方案,我都是耳朵. 这是我实现的另一个通用函数,它比上面有点棘手,因为返回类型与参数类型不同.即,输入是A的序列,但输出是(A,A)的序列: def zipWithSelf[A,It[A] <: Iterable[A]] (xs: It[A] with IterableLike[A,It[A]]) (implicit bf: CanBuildFrom[It[A],(A,A),It[(A,A)]]): It[(A,A)] = { val retval = bf() if (xs.nonEmpty) { retval ++= xs zip xs.tail retval.result } else retval.result } 这是另一个: /** Calls `f(x)` for all x in `xs` and returns an Iterable containing the indexes for * which `f(x)` is true. * * The type of the returned Iterable will match the type of `xs`. */ def findAll[A,It[A]]) (f: A => Boolean) (implicit bf: CanBuildFrom[It[A],Int,It[Int]]): It[Int] = { val retval = bf() retval ++= xs.zipWithIndex filter { p => f(p._1) } map { _._2 } retval.result } 我仍然没有对“Like”类型和CanBuildFrom有任何深刻理解,但我得到了要点.在大多数情况下,将通用函数的转换版本编写为第一遍是很容易的,然后添加CanBuildFrom和IterableLike样板以使函数更通用且完全类型安全. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |