【问题标题】:Trouble using Implicit Ordered with PriorityQueue (Scala)使用带有 PriorityQueue (Scala) 的隐式排序时遇到问题
【发布时间】:2013-02-13 04:01:28
【问题描述】:

我正在尝试创建一个包含PriorityQueue 的数据结构。我已经成功地制作了它的非通用版本。我可以说它有效,因为它解决了人工智能。我遇到的问题。
这是它的一个sn-p:

class ProntoPriorityQueue { //TODO make generic

implicit def orderedNode(node: Node): Ordered[Node] = new Ordered[Node] {
   def compare(other: Node) = node.compare(other)
}

val hashSet = new HashSet[Node]
val priorityQueue = new PriorityQueue[Node]()
...

我正在尝试使其通用,但如果我使用此版本,它将无法解决问题:

class PQ[T <% Ordered[T]] {
//[T]()(implicit val ord: T => Ordered[T]) {
//[T]()(implicit val ord: Ordering[T] {

val hashSet = new HashSet[T]
val priorityQueue = new PriorityQueue[T]
...

我也尝试了注释掉的内容,而不是使用[T &lt;% Ordered[T]]

这里是调用PQ的代码:

//the following def is commented out while using ProntoPriorityQueue
implicit def orderedNode(node: Node): Ordered[Node] = new Ordered[Node] {
     def compare(other: Node) = node.compare(other)
} //I've also tried making this return an Ordering[Node]

val frontier = new PQ[Node] //new ProntoPriorityQueue
//have also tried (not together): 
val frontier = new PQ[Node]()(orderedNode)

我也尝试将隐式 def 移动到 Node 对象中(并导入它),但基本上是同样的问题。

我在通用版本中做错了什么?我应该把隐式放在哪里?


解决方案 问题不在于我的隐含定义。问题是隐式排序被Set 拾取,它在for(...) yield(...) 语句中自动生成。这会导致产生的集合只包含一个状态的问题。

【问题讨论】:

    标签: scala priority-queue implicits


    【解决方案1】:

    在您的 Node (Ordering[Node]) 上简单地定义一个 Ordering 并使用已经通用的 Scala PriorityQueue 有什么问题?

    作为一般规则,使用Ordering[T] 比使用T &lt;: Ordered[T]T &lt;% Ordered[T] 更好。从概念上讲,Ordered[T] 是类型本身的内在(继承或实现)属性。值得注意的是,一个类型只能有一个以这种方式定义的内在排序关系。 Ordering[T] 是排序关系的外部规范。可以有任意数量的不同Ordering[T]

    另外,如果你还不知道,你应该知道T &lt;: UT &lt;% U之间的区别在于前者只包括名义子类型关系(实际继承),后者还包括隐式的应用产生符合类型绑定的值的转换。

    因此,如果您想使用Node &lt;% Ordered[Node],而您没有在类中定义compare 方法,则每次需要进行比较时都会应用隐式转换。此外,如果您的类型它自己的compare,则永远不会应用隐式转换,并且您将被“内置”排序卡住。

    附录

    我将给出几个基于类的示例,称之为CIString,它只是封装了String,并将排序实现为大小写不变。

    /* Here's how it would be with direct implementation of `Ordered` */
    
    class   CIString1(val s: String)
    extends Ordered[CIString1]
    {
      private val lowerS = s.toLowerCase
    
      def compare(other: CIString1) = lowerS.compareTo(other.lowerS)
    }
    
    /* An uninteresting, empty ordered set of CIString1
        (fails without the `extends` clause) */
    val os1 = TreeSet[CIString1]()
    
    
    /* Here's how it would look with ordering external to `CIString2`
        using an implicit conversion to `Ordered` */
    
    class CIString2(val s: String) {
      val lowerS = s.toLowerCase
    }
    
    class CIString2O(ciS: CIString2)
    extends Ordered[CIString2]
    {
      def compare(other: CIString2) = ciS.lowerS.compareTo(other.lowerS)
    }
    
    implicit def cis2ciso(ciS: CIString2) = new CIString2O(ciS)
    
    /* An uninteresting, empty ordered set of CIString2
        (fails without the implicit conversion) */
    val os2 = TreeSet[CIString2]()
    
    
    /* Here's how it would look with ordering external to `CIString3`
        using an `Ordering` */
    
    class CIString3(val s: String) {
      val lowerS = s.toLowerCase
    }
    
    /* The implicit object could be replaced by
        a class and an implicit val of that class */
    implicit
    object  CIString3Ordering
    extends Ordering[CIString3]
    {
      def compare(a: CIString3, b: CIString3): Int = a.lowerS.compareTo(b.lowerS)
    }
    
    /* An uninteresting, empty ordered set of CIString3
        (fails without the implicit object) */
    val os3 = TreeSet[CIString3]()
    

    【讨论】:

    • 我已经尝试在我的节点上扩展 Ordering[Node]。我已经实现了compare(other: Node)compare(some: Node, other: Node) 这在涉及Node 的其他方法调用中引起了一堆问题,下面是其中的一些: - scala.collection.generic.CanBuildFrom[main. Moves.ValueSet,Option[main.Node],That] 从对象 SortedSet 中的方法 newCanBuildFrom 开始 - 方法映射的参数不足:(隐式 bf:scala.collection.generic.CanBuildFrom[main.Moves.ValueSet,Option[main.节点],那个])那个。未指定值参数 bf
    • @Tombstone:你不要让你的Node类扩展Ordering[Node],你定义一个扩展Ordering[Node]的类,它通过定义方法@987654347定义Node上的排序关系@.
    • 我创建了一个扩展 Ordering[Node] 的新类,它可以工作。谢谢你。我还有一个关于隐式的问题。为什么我之前的暗示不起作用? implicit def nodeOrderer: Ordering[Node] = new Ordering[Node]{ def compare(some: Node, other: Node) = some.compare(other) }implicit val ordN: Ordering[Node] = new Ordering[Node] { def compare(some: Node, other: Node) = some.compare(other) }
    • @Tombstone:您必须将正确键入的(它们是)在范围内(如果它们没有被注释掉,它们本来会是)隐式转换 &lt;%类型绑定,而不是代替它。
    • 感谢您的患者帮助我。可悲的是我还没有弄清楚。您能否告诉我您将如何定义类、对构造函数的调用以及要使用的隐式 def?
    【解决方案2】:

    嗯,一个可能的问题是您的Ordered[Node] 不是 Node

    implicit def orderedNode(node: Node): Ordered[Node] = new Ordered[Node] {
      def compare(other: Node) = node.compare(other)
    }
    

    我会尝试使用Ordering[Node],您说您尝试过,但没有更多信息。 PQ 将被声明为 PQ[T : Ordering]

    【讨论】:

    • 我已将PQ 定义更改为:class PQ[T : Ordering] {...,并将我的隐式定义更改为:implicit def orderedNode: Ordering[Node] = new Ordering[Node] { def compare(some: Node, other: Node) = some.compare(other) },但它仍然不起作用
    • @Tombstone 好吧,没有足够的信息。你给我们的只是依赖它的算法不再工作——我怀疑这是算法中的一个错误。在没有“我做 Y 时它做 X,而它应该做 Z”的情况下,我们所能做的就是猜测。
    • 算法可能有问题,但我怀疑有几个原因:1.)它基于我的图搜索算法,该算法适用于探索集的其他数据结构(LIFO, FIFO) 甚至没有探索集 2.) 最大的区别是从堆栈|| 队列更改为优先级队列 3.) 我让它使用非泛型的数据结构工作(现在有一个非-通用的,非隐式版本工作)。放置算法的所有相关信息需要数百行。 dropbox.com/s/lw63j1vq8k94mu4/tombstone%20src.zip
    猜你喜欢
    • 1970-01-01
    • 2021-09-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-11-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多