尝试在Scala中实现LinkedList。我很乐意在scala中创建一个不可变的List作为ADT,如下所示。
sealed trait List[+A]
case object Nil extends List[Nothing]
case class Cons[+A](head: A, tail: List[A]) extends List[A]
但是在scala中尝试创建一个带有“null”终止的java样式链表似乎很难,因为Scala中有一个空引用。
我尝试了以下
sealed trait Node[+A]
case object Empty extends Node[Nothing]
case class LinkedList[A](var head: A,var tail: Node[A]) extends Node[A]
LinkedList是一个具有可变成员的案例类,对我来说似乎非常错误。但由于我必须在每次操作之前区分Empty和LinkedList,我需要模式匹配的帮助。
这是正确的方法吗?或者有更好的方法吗?
同样在第二个例子中,我无法拥有像这样的共同变体类型
case class LinkedList[+A](var head: A,var tail: Node[A]) extends Node[A]
答案 0 :(得分:1)
但是由于我必须在每次操作之前区分Empty和LinkedList,我需要模式匹配的帮助。
不,你不应该这样做。向Node
添加方法,并在Empty
和LinkedList
中以不同方式实施。{}当您需要模式匹配时,您可以:
val x: Node[A] = ...
x match {
case Empty => ...
case nonEmpty: LinkedList[A] => ... // use nonEmpty
不使LinkedList
成为案例类的原因只是它自动允许对链表无意义的操作。
此外,您当前的定义不允许创建空列表,然后向其添加元素(而不是创建新列表)。对于可变链表,列表不能 节点;它应将引用到节点。
作为一个起点:
object LinkedList {
private sealed trait MaybeNode[A] // can't be covariant!
private case class Empty[A]() extends MaybeNode[A]
private class Node[A](var value: A, var next: MaybeNode[A])
}
class LinkedList[A] {
private var first: MaybeNode[A] = Empty()
def add(x: A): Unit = ???
def length: Int = ???
// any other methods you want to support
}
(这是一个单链接的列表,而不是像Java中那样的双重链接列表。)