Iterable
的三个直接子类型为Map
,Seq
和Set
。似乎除了性能问题之外 - Seq
是从整数到值的映射,Set
是从值到布尔值的映射(如果值在集合中则为true,否则为false)
如果是这种情况,为什么不通过Seq[V]
扩展Map[Int, V]
和Set[V]
扩展Map[V, Boolean]
来在类型系统中表达?
答案 0 :(得分:12)
嗯,他们有点做,至少实际上是常见的功能。 Seq[B]
继承自Int => B
(来自PartialFunction[Int, B]
),Map[A, B]
继承自A => B
(也来自PartialFunction[A, B]
),Set[A]
继承来自A => Boolean
。因此,就功能应用和组合方法而言,所有三种都可以互换使用。此外,就遍历而言,它们可以互换使用,因为所有实现TraversableLike
。
答案 1 :(得分:8)
将序列视为从整数到元素的赋值只是描述序列是什么的一种方式。还有其他方法,没有理由说这种描述序列的方式应该成为规范。序列的实际目的是使一堆元素可访问和遍历。不需要序列来实际为元素分配整数。例如,大多数Stream
实现可能没有与遍历并行运行的计数器。要求这会给实施带来不必要的开销。
此外,Map[K,V]
也是Iterable[(K,V)]
。根据您的建议,Seq[A]
也必须是Map[Int,A]
,这也会使其成为Iterable[(Int,A)]
。由于Seq
扩展Iterable
,这会使Seq[A]
同时成为Iterable[A]
和Iterable[(Int,A)]
(并且,递归地,Iterable[(Int,(Int,A))]
,{{ 1}},等等,这不是Scala中允许的继承方式。
您可以针对Iterable[(Int,(Int,(Int,A)))]
。
答案 2 :(得分:4)
好吧,如果所有你关心的是Seq
而Set
就是那个,那么你有一个观点。我自己,我碰巧认为这是最不重要的方面之一,而且已经很好地代表了所有这些方面的功能。
也就是说,Map
是值中的键的函数,Seq
是值Int
的函数,而Set
是值的函数为Boolean
。这个属性,你称之为“地图”,是一个功能。它已经被所有三个人共享。
在我看来,Map
,Seq
和Set
的真正含义是:
Seq
关注的是知道其元素的顺序。从概念上讲,您如何在Map
中添加元素?你必须重新编号所有键!
Set
关注元素的存在与否。如何在Map
中对此进行建模?它必须是具有默认值的地图 - 不是公共地图 - 并且所有非默认值都相同!这显然是一种堕落的行为,而不是一种抽象。
Map
关注将任意键映射到任意值。 Seq
没有任意密钥,Set
没有任意值。