如何最好地在功能集合上实现ID系统

时间:2017-11-01 00:25:57

标签: scala functional-programming

在我的项目中,我使用Seq[Drone]来跟踪世界中的无人机。它是一个功能项目,所以世界和无人机都是案例类的价值。

在世界process()方法中,返回一个新的World实例,其中包含该序列的转换版本,并且因为它是无序的,所以没有保证无人机以相同的顺序返回。这是设计初步实施的。

现在,现在是时候实施ID系统,以便可以单独分配动作(例如" d1移动到(4,6)")。这意味着无人机需要以保留" order"的方式存储。

我花了一些时间提出了几种方法,但首先,确定了ID 如何工作的方式。

ID行为

  • ID对于所有现有无人机(世界上的无人机)都是唯一的。
  • 当无人机到期时,其ID将被释放。
  • 添加无人机时,它会获得最低的可用ID。 (这意味着可以重复使用ID。)
  • Drone类型没有ID - 这是一个仅由World赋予意义的概念。

选项1:普通元组

我的Seq[Drone]将成为Vector[(Int, Drone)]。对无人机的引用将从world.drones(n)更改为world.drones(n)._2,这有很多原因。 ID可以通过world.drones(n)._1访问。

选项2:类型别名元组

我将名为D的类型添加到(Int, Drone),并将Seq[Drone]更改为Vector[D]。我相信这与选项1有类似的问题,尽管我没有很多关于类型化的经验。

选项3:案例类

我制作case class D(id: Int, drone: Drone)之类的内容并将Seq[Drone]变为Vector[D]作为选项2.这样做的好处是可以提供更好的通话(d.id和{{ 1}}而不是元组语法),并且几乎可以用于元组(d.drone vs D(1, Drone()) - 单个字符的区别)。

我的问题是:选项3是一个合适的解决方案吗?如果是这样,我将来会遇到哪些问题? (我设想一些工作来整理电话,但除此之外什么都没有。)如果没有,我可以通过哪些途径找到更适合的电话?

1 个答案:

答案 0 :(得分:2)

所有3个选项几乎相同。 2元组实际上只是一个名为Tuple2的案例类,其中Scala添加了一些语法糖,因此您可以编写(a, b)而不是Tuple2(a,b)。因此,考虑到这些选项,我会选择选项3,因为更具描述性的方法名称。事实上,由于这个原因,通常不鼓励使用元组。

但是还有另一种可能性,请使用Map[Int, Drone]。这将为您提供开箱即用的一些功能(包括通过id和唯一性检查快速查找)并完成相同的操作,而无需定义您自己的新类型。

例如,您可以定义将无人机添加为:

def addDrone(drones: Map[Int, Drone], newDrone : Drone): Map[Int, Drone] = {
  val id = (0 until drones.size).find(!drones.contains(_)).getOrElse(drones.size)
  drones + (id -> newDrone)
}

并且释放id就像从地图中删除它一样简单。