我已经意识到我传递Scala集合的典型方式可以使用一些改进。
def doSomethingCool(theFoos: List[Foo]) = { /* insert cool stuff here */ }
// if I happen to have a List
doSomethingCool(theFoos)
// but elsewhere I may have a Vector, Set, Option, ...
doSomethingCool(theFoos.toList)
我倾向于编写我的库函数以List
作为参数类型,但我确信我可以放置一些更通用的东西来避免我偶尔发生的所有.toList
调用在应用程序代码中。这尤其令人讨厌,因为我的doSomethingCool
函数通常只需要调用map
,flatMap
和filter
,这些都是在所有集合类型上定义的。
对于那种“更普遍的东西”,我有哪些选择?
答案 0 :(得分:6)
以下是更一般的特征,每个特征都扩展了前一个特征:
GenTraversableOnce
GenTraversable
GenIterable
GenSeq
上述特征未指定集合是顺序还是并行。如果您的代码要求按顺序执行某些操作(通常,如果您的代码具有任何类型的副作用),则它们过于笼统。
以下特征要求顺序执行:
TraversableOnce
Traversable
Iterable
Seq
LinearSeq
第一个,TraversableOnce
只允许您在集合上调用一个方法。之后,该集合已被“使用”。作为交换,它通常足以接受迭代器和集合。
Traversable
是一个非常通用的集合,拥有大多数方法。但有些事情是无法做到的,在这种情况下你需要转到Iterable
。
所有Iterable
实施iterator
方法,这样您就可以获得该集合的Iterator
。这使它能够使用Traversable
中没有的一些方法。
Seq[A]
实现函数Int => A
,这意味着您可以通过索引访问任何元素。这不能保证有效,但它保证每个元素具有索引,并且您可以对该索引的内容进行断言。将此与Map
和Set
进行对比,您无法分辨元素的索引是什么。
LinearSeq
是Seq
,提供快速head
,tail
,isEmpty
和前置。这与List
尽可能接近,而没有明确使用List
。
或者,您可以拥有IndexedSeq
,它具有快速索引访问权限(List
未提供的内容)。
另请参阅this question和this FAQ。
答案 1 :(得分:4)
最明显的一个是使用Traversable
作为最一般特征,这将具有您想要的好东西。但是,我认为你通常会更好地坚持:
Seq
IndexedSeq
Set
Map
Seq
将涵盖List
,Vector
等,IndexedSeq
将涵盖Vector
等等。我发现自己没有使用Iterable
,因为我经常需要(或想要)知道我所拥有的东西的大小并且知道pre scala-2.8 Iterable
did not provide access to this,所以我总是不得不把事情变成序列!
看起来Traversable
和Iterable
现在有size
方法,所以我应该回去使用它们!当然你可以用GenTraversableOnce
开始“疯狂”,但这不太可能有助于提高可读性。