如何使一个类成为 Scala 中两个链表的成员?
我有一种感觉,我在这里遗漏了一些非常明显的东西。
作为学习练习,我正在将用 Java 编写的编译器生成器转换为 Scala。
它并不是真正用Java编写的,它似乎是音译为C的。
在程序的一部分中,有Nodes。每个节点都是两个链表的一部分,并且有一些字段是对每个链表中下一项的引用(称为“跨”和“下”)。各种方法遍历这些列表(其中一个或两个)并对每个访问的节点执行操作。
我想使用 Scala 的集合而不是这些显式引用,因为有很多样板代码遍历并向这些列表添加内容。我该怎么做?列表是相当多变的,所以我想使用可变列表
我想我不想要节点的链接列表,因为每个节点都需要知道它的下一个跨(或下)邻居是什么,无论我如何到达这个节点所以我需要能够从 Node 转到任一列表。
我可以从 LinkedList 继承,但我需要这样做两次(一次是横向的,一次是向下的)。
我可以有两个内部类(crosslist 和 downlist),每个内部类都是 LinkedList 的实例,但它们可以是 LinkedList[Node] 吗?我无法理解这是如何工作的,因为列表的下一个引用需要是 node.acrosslist.next (比如说),而对于 LinkedList 来说它只是“下一个”。
所以,请指出明显的,或者如果不明显的话,我如何让它发挥作用!
I have a feeling I'm missing something very obvious here.
I'm converting a compiler generator written in Java into Scala as a learning exercise.
It's not really written in Java, it seems to be transliterated C.
In one part of the program, there are Nodes. Each node is part of two linked lists, and there are fields that are references to the next item in each of the linked lists (call these "across" and "down"). Various methods traverse these lists, either one of them or both of them and do things to each visited node.
I'd like to use Scala's collections instead of these explicit references, since there's a lot of boilerplate code traversing and adding stuff to these lists. How do I do this? The lists are quite changeable so I want to use mutable lists
I think I don't want a linked list of Node, because each Node needs to know what its next across (or down) neighbor is, regardless of how I got to this node so I need to be able to go from Node to either list.
I could inherit from LinkedList, but I need to do that twice (once for across and once for down).
I could have two inner classes (acrosslist and downlist) each an instance of LinkedList, but can they be LinkedList[Node]? I can't get my head around how this would work, as the 'next reference for the list would need to be node.acrosslist.next (say) and for LinkedList it's just "next".
So, please point out the obvious, or if not obvious, how I get this to work!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
为什么不自己将事物链接起来,然后在每个方向创建迭代器?
Why don't you link things up yourself, and then create iterators in each direction?
让我详细介绍一下 Rex Kerr 的 答案。 Scala 的所有集合实际上包含三个中心类,但其中只有两个真正属于集合的一部分。它们是
Traversable
、Iterable
和Iterator
。最基本的集合是
Traversable
。要成为Traversable
,只有一个先决条件:它需要实现foreach
方法。因此,只要可以传递一个函数,然后将该函数应用于集合的每个元素,它就可以是一个Traversable
。例如:这将为您提供所有
Traversable
方法,尽管map
和filter
等方法不会返回Three< /code>,而是一个
可遍历
。让它返回您定义的类要困难得多,许多专门的类无法做到这一点。例如,Three
无法做到这一点,因为删除一些元素的filter
的Three
是什么?接下来是
Iterator
,它的功能与Traversable
几乎相同,但方式不同。Iterator
必须定义两个方法:next
和hasNext
。例如:这将给出
Iterator
的所有方法,它们大部分看起来与Traversable
中的方法相同。这些方法之间的差异主要与迭代器只能使用一次这一事实有关。最后,还有
Iterable
。要成为Iterable
,类必须实现一个方法:iterator
,该方法返回该类的Iterator
。例如:那么,回到你的问题,你必须考虑你想要的预期行为是什么,以及你想要如何实现它。特别是,Scala 集合中没有“向下”和“向左”的概念,这意味着
Node
可以有一个返回 Scala 集合的方法,但永远不可能是一个正确地说,就像我们在 Rex Kerr 的解决方案中看到的那样。编辑
让我举一个与 Rex Kerr 不同的例子。这里我将做一个
Traversable
Node
,并且遍历的顺序是可选择的。所以这个
Node
是Traversable
,并且它支持所有Traversable
方法(尽管它仍然不会返回Node
> 来自map
等 - 查找与此相关的其他问题)。您可以使用标志 (traverseLeft
) 选择它是向左还是向下遍历,所有普通的Traversable
方法都将使用调用该方法的节点中设置的任何内容。然而,这不是一个好的模型。我宁愿采用 Rex Kerr 的将迭代器返回到左侧和向下的解决方案,或者完全保留 Scala 集合并使用 Kiama。不过,后者是一个完全不同的范例,您不会将其硬塞到转写为 Scala 的代码中。
Let me expand a bit on Rex Kerr's answer. There are really three central classes to all of Scala's collection, and only two of them are really part of the collections. They are
Traversable
,Iterable
andIterator
.The most basic collection is the
Traversable
. There's only one requisite for something to be aTraversable
: it needs to implement the methodforeach
. So, as long as one can pass a function which will then be applied to each element of the collection, it can be aTraversable
. For example:This will give you all of
Traversable
methods, though methods such asmap
andfilter
won't return aThree
, but aTraversable
. Getting it to return the class you defined is much more difficult, and many specialized classes just can't do it. For example,Three
can't do it, because what would be theThree
of afilter
which removed some elements?Next, there's the
Iterator
, which really does pretty much the same thing asTraversable
, but in a different manner. AnIterator
has to define two methods:next
andhasNext
. For example:This will give all methods of
Iterator
, which mostly look the same as the methods inTraversable
. The difference between the methods are mostly related to the fact that anIterator
can only be used once.Finally, there's
Iterable
. To be anIterable
, a class has to implement one method:iterator
, which returns anIterator
for that class. For example:So, back to your question, you have to consider what is the expected behavior you want, and how do you want it. In particular, there's no notion of "down" and "left" in Scala collections, which means a
Node
could have a method returning a Scala collection, but could never be one properly speaking, such as we see on Rex Kerr's solution.EDIT
Let me give an example distinct from Rex Kerr's. Here I'll do a
Traversable
Node
, and the order of traversal will be selectable.So this
Node
isTraversable
, and it supports all ofTraversable
methods (though it still won't return aNode
frommap
, etc -- look up other questions about this). You can select whether it will traverse left or down with a flag (traverseLeft
), and all normalTraversable
methods will use whatever is set in the node where the method was called.This, however, is not a good model. I'd rather go with Rex Kerr's solution of returning iterators to left and down, or leave Scala collections completely and go with something processed with Kiama. The latter is a completely different paradigm, though, and not something you are going to shoe-horn into a code being transliterated to Scala.