- About Scala
- Documentation
- Code Examples
- Software
- Scala Developers
abstracting across pimpiness
Tue, 2010-09-14, 06:30
Astute hypothetical observers will have noticed that the traversable-2.9
patch works hard not to get tangled up in the trunk wires:
-trait SeqLike[+A, +Repr] extends IterableLike[A, Repr] { self =>
+trait SeqLike[+A, +Repr] extends IterableLike[A, Repr] with SeqExtensions[A, Repr] { self =>
+ with TraversableExtensions[A, Repr]
-trait TraversableOnce[+A] {
+trait TraversableOnce[+A] extends TraversableOnceExtensions[A] {
That's the extent of the changes to existing files. This is the most
important thing you can do if you are the sort of person who writes lots
of code and then sometimes forgets about it and lets it sit in a branch
for half a year or more and then one day you want to check it in, not
that I know anyone like that.
To the point. Johnny has written a trait containing five methods. He'd
like to put it in trunk, but in the end it'll be up to Prof. McTyperson.
If Prof. McTyperson puts the kibosh on Johnny's trait, he'd still like
to utilize the methods in the manner of the pimps.
So the question is, how should Johnny structure the code to ruthlessly
minimize the number of changes he'd have to make to change it from
"vulcan implementation meld" style to "pimpy wrapper" style? And what
stands in the way of a toll-free road? As an example, one heavy blow is
losing access to protected methods: toCollection is one such.
Johnny's sample trait:
trait SeqExtensions[+A, +Repr] {
self: SeqLike[A, Repr] =>
def promoteIndex(index: Int): Repr = {
val it = iterator drop index
newBuilder += it.next ++= (iterator take index) ++= it result
}
def dropIndex(index: Int): Repr =
extractIndex(index)._2
def extractIndex(index: Int): (A, Repr) = {
val it = iterator drop index
(it.next, newBuilder ++= (iterator take index) ++= it result)
}
def splitAround(index: Int): (Repr, A, Repr) = {
val (xs, ys) = splitAt(index)
val it = toCollection(ys).iterator
(xs, it.next, newBuilder ++= it result)
}
def permutations: Iterator[Repr] = {
def distinctIndices = toCollection(distinct) map (x => indexOf(x)) iterator;
if (isEmpty) Iterator.empty
else if (thisCollection.tail.isEmpty) Iterator(repr)
else distinctIndices map (thisCollection splitAround _) flatMap {
case (front, el, back) => (front ++ back).permutations map (newBuilder += el ++= _ result)
}
}
}