Ошибка PriorityQueue varargs при расширении Ordering для размещения объектов класса - PullRequest
0 голосов
/ 31 декабря 2018

Моя цель - создать функцию, которая принимает переменные из 2 или более объектов при инициализации PriorityQueue, содержащей указанные объекты.

Соответствующий код:

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):

[ошибка] найдена: TopicTrenderInit.FreqOrdering.type
[ошибка] требуется: scala.math.Ordering [Equals]
[error] Примечание: TopicTrenderInit.Topic <: Equals (и TopicTrenderInit.FreqOrdering.type <: scala.math.Ordering [TopicTrenderInit.Topic]), но с признакомПорядок инвариантен для типа T. <br>[ошибка] Вы можете захотеть исследовать подстановочный тип, такой как _ <: Equals.(SLS 3.2.10)
[ошибка], возвращать PriorityQueue (a, b, c) (FreqOrdering)
[ошибка] ^
[ошибка] / home / aaron-laptop / Documents / Scala / topic_trender100 /src / main / scala / main.scala: 48: 25: несоответствие типов;
[ошибка] найдена: scala.collection.mutable.PriorityQueue [равно]
[ошибка] требуется: scala.collection.mutable.PriorityQueue[TopicTrenderInit.Topic]
[ошибка] Примечание: равно:: TopicTrenderInit.Topic, но класс PriorityQueue инвариантен в типе A.
[ошибка] Возможно, вы захотите исследовать подстановочный тип, например _ >: TopicTrenderInit.Topic.(SLS 3.2.10)
[ошибка] return PriorityQueue (a, b, c) (FreqOrdering)

Когда нет '*', указывающего на переменную, все работает, ошибок нет.Я думаю, что самое худшее, что меня смущает, - это необходимость: ошибка scala.math.Ordering [Equals].Я также прочитал статью о сопоставлении с образцом, но я чувствую, что мне придется прочитать больше об этом, чтобы понять реализацию.Что здесь происходит?
Спасибо.

Ответы [ 2 ]

0 голосов
/ 31 декабря 2018

Проблема в том, как вы строите 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.

0 голосов
/ 31 декабря 2018

Проблема в том, что, когда вы передаете a, b, c на Factory из PriorityQueue.Компиляторы видят, что вы передали три аргумента типа A, и единственный супертип между этими деревьями - Equals.
. Это потому, что a & b равны Topics, что в данном случаекласс расширяет Equals, а c имеет тип Seq[Topic] (аргументы varargs передаются как 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): _*)
...