【问题标题】:Scala: working around the "illegal cyclic reference"Scala:解决“非法循环引用”
【发布时间】:2011-02-13 12:25:23
【问题描述】:

我正在尝试实现一个基于 HashMap 的树,它支持对给定根键的 O(1) 子树查找。为了这个目标,我正在尝试做以下事情:

scala> type Q = HashMap[Char, Q]
<console>:6: error: illegal cyclic reference involving type Q
       type Q = HashMap[Char, Q]
                          ^

所以问题是,我有没有办法在不诉诸丑陋的HashMap[Char, Any] 并随后将值转换为HashMap[Char, Any] 的情况下做类似的事情?

现在,我还发现我可以使用类似以下的方法来避免循环引用错误,而且它甚至可能更简洁——但如果能以第一种方式正确地进行操作,那就太好了,只是为了教育价值。

import collections.mutable.HashMap

class LTree {
  val children = new HashMap[Char, LTree]
}

非常感谢。

【问题讨论】:

  • 你能澄清一下你想定义什么样的结构吗?一棵树的弧标有Char,其节点根本不包含任何信息?如果是这样,您的LTree 几乎是最小的,但正如所写的那样,您只能创建空树,因为childrenHashMap 本身一样是不可变的,并且构造函数不接受任何参数。
  • 感谢兰德尔的评论。我刚刚调整了上面的清单以表明(就像在我的源代码中一样)使用的 HashMap 是可变的。用例确实是一个有向图,带有 char 标记的边和不包含任何信息的节点。这实际上是一个基本的 DFA,其中叶节点隐含地考虑了最终状态。无论如何,以上内容与 scala 语法问题无关——我想我给出的小 sn-p 是一种解决方法,我只是好奇是否有办法更简洁地做到这一点,因为建议在第一个清单中。
  • 当然,实际上,LTree 的第二种方式更合适,因为我可以在其中为各种树操作折腾字段和成员函数。
  • 我们必须承认的一件事是 Scala 虽然通常比 Java 简洁得多,但通常仍被 Haskell 击败。我还应该指出,Scala 的 type 声明只为现有类型命名别名,它们不会发明新类型。在这方面,Scala 的 type 类似于 Haskell 的 type,而不是它的 newtype
  • neopythonic.blogspot.com/2008/11/scala.html 上有一个关于 Scala 优点和缺点的有趣讨论。在我同意的一些 cmets 中,有一个来自 Alex Payne:In Haskell's 18 years on the programming language scene, it's been in the perpetual role of the underused theoretical ideal alternative. I can't count how many times I've seen "perhaps Haskell?" since researching languages became a hobby of mine. I'm seeing more and more programmers getting real work with Scala, not musing about its theoretical possibilities. I find that pragmatism encouraging.

标签: scala tree types


【解决方案1】:

我可能没有“明白”这个问题,但是呢

class L {
  type Q = java.util.HashMap[Char, this.type]
}

class Q extends java.util.HashMap[Char, Q]

【讨论】:

  • 谢谢阿特姆!这两项工作,这正是我一直在寻找的。 Спасибо! :)
  • 你能解释一下第一个吗?
【解决方案2】:

对于你不能extend的类型,比如Either,你也可以使用一个简单的包装器:

class MyEither(get: Either[String, MyEither])

或者,带有Either 的递归树(导致我进入这个线程的东西):

// represents (validation) errors for a tree structure of nested dictionaries
type FieldName = String
type Error = String

type Errors = List[(FieldName, FieldError)]
case class FieldError(val get: Either[Error, Errors])

这是此伪代码的类型合法版本:

type Error = String
type Errors = List[(FieldName, Either[Error, Errors])]

然后,您的所有Left(...)Right(...) 调用将分别变为FieldError(Left(...))FieldError(Right(...)),例如FieldError(Right(x)).get == Right(x).

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-10-19
    • 1970-01-01
    • 2012-11-05
    • 1970-01-01
    • 2017-09-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多