« Return to Thread: Towards a revised collection API

Re: Towards a revised collection API

by Christos KK Loverdos :: Rate this Message:

Reply to Author | View in Thread

Have you seen the paper "Generics of a Higher Kind"?

http://lambda-the-ultimate.org/node/2579

They introduce a Buildable trait that does the job. Moreover, Martin
has just said in scala-debate that they are redesigning the
collections in order to use the ideas in the paper, and they do so in
a backwards-compatible way. It will take them a couple of months
before they go public.



On Fri, Apr 18, 2008 at 2:28 PM, David MacIver <david.maciver@...> wrote:

> So, with the recent noise I've been making about the collections API,
>  I figured I should put some thoughts down on screen.
>
>  As I see it one of the main problems with the current collection API
>  is that in order to make things play nicely you need to override
>  methods at every step of the way. map, filter, flatMap etc all return
>  the "wrong" things. This is a pain to write and easy to get wrong.
>
>  The other thing I don't like about the collections API is that I'm not
>  a big fan of iterators. They're really cumbersome to create for custom
>  collection types and are designed around a really irritating "check
>  then proceed" style. Really all we care about is how to traverse the
>  data structure, and constructing an iterator to do so is often not the
>  best way.
>
>  Here's something I threw together last night to try to address these
>  problems. The basic principles are:
>
>  - It should be easy to convert between collection types
>  - Consequently it's ok if we return the "wrong" thing.
>  - In fact it may be desirable to do so!
>  - All we care about generically are how to traverse a data structure
>  and how to build one, so these are the operations the API should be
>  designed around.
>
>  So the API defines a trait Enumerable which describes how to traverse
>  a structure and a trait Buildable which describes how to build one
>  (the data structure doesn't implement Buildable, one makes an implicit
>  instance available). Implementations do not override the enumerable
>  map, flatMap, etc. methods - these continue to return a generic
>  enumerable. However at the end of a bunch of operations you explicitly
>  "cast" to the desired result.
>
>  So for example
>
>  scala> for (i <- range(1, 4); j <- range(1, 4); if (i != j)) yield (i, j)
>  res8: enumerable.Enumerable[(Int, Int)] = enumerable.Enumerable$$anon$4@708aff
>
>  scala> res8.intersperse(",").mkString
>  res9: String = (1,2),(1,3),(2,1),(2,3),(3,1),(3,2)
>
>  scala> res8.as[List, (Int, Int)]
>  res10: List[(Int, Int)] = List((1,2), (1,3), (2,1), (2,3), (3,1), (3,2))
>
>  (you need to specify the type like that in order to make this work
>  because of Enumerable being covariant in its type)
>
>  I've not benchmarked, but for large for comprehensions this should
>  actually be more efficient, as it avoids the construction of
>  intermediate datastructures.
>
>  We can use return from inside passed closures to control evaluation
>  and exit the loop prematurely, which allows efficient implementation
>  of things like exists, foreach and take. For example:
>
>  scala> def from(x : Int) = new Enumerable[Int] { def foreach(f : Int
>  => Unit) = {var i = x; while(true) { f(i); i =} } } i + 1} } }
>  from: (Int)java.lang.Object with enumerable.Enumerable[Int]
>
>  scala> from(0).take(10).foreach(println);
>  0
>  1
>  2
>  3
>  4
>  5
>  6
>  7
>  8
>  9
>
>  The exact structure of Buildable needs work (it doesn't currently
>  handle sorted collections well for example), but I'm reaonably happy
>  with how Enumerable works.
>
>  Any thoughts?
>



--
 __~O
 -\ <, Christos KK Loverdos
(*)/ (*) http://ckkloverdos.com

 « Return to Thread: Towards a revised collection API