扩展 Ordering 以容纳 class 个对象时出现 PriorityQueue varargs 错误
PriorityQueue varargs error when extending Ordering to accomodate class objects
我的目标是创建一个函数,在初始化包含所述对象的 PriorityQueue 时采用 2 个或更多对象的可变参数。
相关代码为:
case class Topic(topic: String, usageFrequency: Long = 1)
object FreqOrdering extends Ordering[Topic] {
def compare(a: Topic, b:Topic) = -(a.usageFrequency compare b.usageFrequency)}
def initPriQu(a : Topic, b: Topic, c: Topic*): PriorityQueue[Topic] = {
return PriorityQueue(a,b,c)(FreqOrdering)}
sbt (Scala 2) 错误:
[error] found : TopicTrenderInit.FreqOrdering.type
[error] required: scala.math.Ordering[Equals]
[error] Note: TopicTrenderInit.Topic <: Equals (and TopicTrenderInit.FreqOrdering.type <: scala.math.Ordering[TopicTrenderInit.Topic]), but trait Ordering is invariant in type T.
[error] You may wish to investigate a wildcard type such as _ <: Equals
. (SLS 3.2.10)
[error] return PriorityQueue(a,b,c)(FreqOrdering)
[error] ^
[error] /home/aaron-laptop/Documents/Scala/topic_trender100/src/main/scala/main.scala:48:25: type mismatch;
[error] found : scala.collection.mutable.PriorityQueue[Equals]
[error] required: scala.collection.mutable.PriorityQueue[TopicTrenderInit.Topic]
[error] Note: Equals >: TopicTrenderInit.Topic, but class PriorityQueue is invariant in type A.
[error] You may wish to investigate a wildcard type such as _ >: TopicTrenderInit.Topic
. (SLS 3.2.10)
[error] return PriorityQueue(a,b,c)(FreqOrdering)
当没有“*”表示可变参数时,一切正常,没有错误。我认为最让我困惑的是 required: scala.math.Ordering[Equals] 我看到的错误。我还阅读了一篇关于模式匹配的文章,但我觉得我必须阅读更多内容才能理解实现。这是怎么回事?
谢谢。
问题在于,当您将 a, b, c
传递给 PriorityQueue
的 Factory 时。编译器看到的是您传递了三个 A
类型的参数,并且这些树之间唯一的超类型是 Equals
.
这是因为 a
和 b
是 Topics
,在这种情况下 class 扩展了 Equals
,而 c
是类型 Seq[Topic]
(可变参数作为 Seq
传递),它还扩展了 Equals
.
这就是为什么它要求 Ordering[Equals]
.
您可以按如下方式修复。
(请注意,这非常丑陋而且可能微不足道,您可以考虑只接收一个可变参数而不是 a
& b
然后 c
)
// It will be good to have this as an implicit so you don't have to pass it explicitly
// every time you need to.
// And it is always preferable to have an implicit val with an explicit type signature
// than an implicit object.
implicit val TopicOrdering: Ordering[Topic] = new math.Ordering[Topic] {
override def compare(a: Topic, b:Topic): Int =
-(a.usageFrequency compare b.usageFrequency)
}
import scala.collection.mutable.PriorityQueue
def initPriQu(a: Topic, b: Topic, others: Topic*): PriorityQueue[Topic] =
// 1. Don't use return in scala.
// 2. Here I made a Seq of Seqs of Topic - Seq[Seq[Topic]]
// then I flatten it to have a Seq of Topic - Seq[Topic]
// and finally used the ':_*' operator to turn a Seq into a varargs.
PriorityQueue((Seq(a, b) ++ others): _*)
问题在于您构建 PriorityQueue
的方式。您向它传递了两个 Topic
类型的值和一个 Seq[Topic]
类型的值,因此结果为 PriorityQueue[Any]
.
这应该有效:
def initPriQu(a : Topic, b: Topic, c: Topic*): mutable.PriorityQueue[Topic] =
mutable.PriorityQueue(Seq(a, b) ++ c:_*)(FreqOrdering)
此外,不要使用 return
。
我的目标是创建一个函数,在初始化包含所述对象的 PriorityQueue 时采用 2 个或更多对象的可变参数。
相关代码为:
case class Topic(topic: String, usageFrequency: Long = 1)
object FreqOrdering extends Ordering[Topic] {
def compare(a: Topic, b:Topic) = -(a.usageFrequency compare b.usageFrequency)}
def initPriQu(a : Topic, b: Topic, c: Topic*): PriorityQueue[Topic] = {
return PriorityQueue(a,b,c)(FreqOrdering)}
sbt (Scala 2) 错误:
[error] found : TopicTrenderInit.FreqOrdering.type
[error] required: scala.math.Ordering[Equals]
[error] Note: TopicTrenderInit.Topic <: Equals (and TopicTrenderInit.FreqOrdering.type <: scala.math.Ordering[TopicTrenderInit.Topic]), but trait Ordering is invariant in type T.
[error] You may wish to investigate a wildcard type such as_ <: Equals
. (SLS 3.2.10)
[error] return PriorityQueue(a,b,c)(FreqOrdering)
[error] ^
[error] /home/aaron-laptop/Documents/Scala/topic_trender100/src/main/scala/main.scala:48:25: type mismatch;
[error] found : scala.collection.mutable.PriorityQueue[Equals]
[error] required: scala.collection.mutable.PriorityQueue[TopicTrenderInit.Topic]
[error] Note: Equals >: TopicTrenderInit.Topic, but class PriorityQueue is invariant in type A.
[error] You may wish to investigate a wildcard type such as_ >: TopicTrenderInit.Topic
. (SLS 3.2.10)
[error] return PriorityQueue(a,b,c)(FreqOrdering)
当没有“*”表示可变参数时,一切正常,没有错误。我认为最让我困惑的是 required: scala.math.Ordering[Equals] 我看到的错误。我还阅读了一篇关于模式匹配的文章,但我觉得我必须阅读更多内容才能理解实现。这是怎么回事?
谢谢。
问题在于,当您将 a, b, c
传递给 PriorityQueue
的 Factory 时。编译器看到的是您传递了三个 A
类型的参数,并且这些树之间唯一的超类型是 Equals
.
这是因为 a
和 b
是 Topics
,在这种情况下 class 扩展了 Equals
,而 c
是类型 Seq[Topic]
(可变参数作为 Seq
传递),它还扩展了 Equals
.
这就是为什么它要求 Ordering[Equals]
.
您可以按如下方式修复。
(请注意,这非常丑陋而且可能微不足道,您可以考虑只接收一个可变参数而不是 a
& b
然后 c
)
// It will be good to have this as an implicit so you don't have to pass it explicitly
// every time you need to.
// And it is always preferable to have an implicit val with an explicit type signature
// than an implicit object.
implicit val TopicOrdering: Ordering[Topic] = new math.Ordering[Topic] {
override def compare(a: Topic, b:Topic): Int =
-(a.usageFrequency compare b.usageFrequency)
}
import scala.collection.mutable.PriorityQueue
def initPriQu(a: Topic, b: Topic, others: Topic*): PriorityQueue[Topic] =
// 1. Don't use return in scala.
// 2. Here I made a Seq of Seqs of Topic - Seq[Seq[Topic]]
// then I flatten it to have a Seq of Topic - Seq[Topic]
// and finally used the ':_*' operator to turn a Seq into a varargs.
PriorityQueue((Seq(a, b) ++ others): _*)
问题在于您构建 PriorityQueue
的方式。您向它传递了两个 Topic
类型的值和一个 Seq[Topic]
类型的值,因此结果为 PriorityQueue[Any]
.
这应该有效:
def initPriQu(a : Topic, b: Topic, c: Topic*): mutable.PriorityQueue[Topic] =
mutable.PriorityQueue(Seq(a, b) ++ c:_*)(FreqOrdering)
此外,不要使用 return
。