- About Scala
- Documentation
- Code Examples
- Software
- Scala Developers
Support for explicit Builders
Fri, 2009-10-23, 12:35
Suppose I have a List whose elements I want to transform, and collect
in an Array.
The new Builder/CanBuildFrom mechanism should make it easy to do this
without constructing an intermediate List, but currently the standard
library doesn't make it particularly obvious how to do it (at least,
if it does, I've missed it).
I think we should do something to make this more straightforward.
It ought to be possible to allow a Builder to act as it's own factory.
The obvious implicit doesn't play all that nicely with type inference,
implicit def builderIsBuilderFactory[From, T, To](b : Builder[T, To]) =
new CanBuildFrom[From, T, To] {
def apply(from: From) = b ; def apply() = b
}
scala> val l = List(1, 2, 3)
l: List[Int] = List(1, 2, 3)
scala> val a = l.map(_ + 1)(Array.newBuilder[Int]) <-- Type param required
a: Array[Int] = Array(2, 3, 4)
scala> val l2 = a.map(_ + 1)(List.newBuilder[Int]) <-- Type param required
l2: List[Int] = List(3, 4, 5)
Making the implicit explicit isn't so bad,
def buildWith[From, T, To](b : Builder[T, To]) =
new CanBuildFrom[From, T, To] {
def apply(from: From) = b ; def apply() = b
}
scala> val l = List(1, 2, 3)
l: List[Int] = List(1, 2, 3)
scala> val a = l.map(_ + 1)(buildWith(Array.newBuilder))
a: Array[Int] = Array(2, 3, 4)
scala> val l2 = a.map(_ + 1)(buildWith(List.newBuilder))
l2: List[Int] = List(3, 4, 5)
But maybe we can do better ... could Builder extend CanBuildFrom in a
way which would allow,
val a = l.map(_ + 1)(Array.newBuilder)
val l2 = a.map(_ + 1)(List.newBuilder)
without either an explicit type parameter or function application?
Thoughts?
Cheers,
Miles
Fri, 2009-10-23, 14:17
#2
Re: Support for explicit Builders
I agree this would be useful (in our OOPSLA paper we called this mapOut). With the current library as a given, I can't think of a better/shorter way to do it than:
import scala.collection.generic._ import scala.collection._import scala.collection.mutable._
def breakOut[From, T, To](implicit b : CanBuildFrom[Nothing, T, To]) = new CanBuildFrom[From, T, To] { def apply(from: From) = b.apply() ; def apply() = b.apply() }
scala> val l = List(1, 2, 3)l: List[Int] = List(1, 2, 3)
scala> val a: Array[Int] = l.map(_ + 1)(breakOut) a: Array[Int] = Array(2, 3, 4)
Unfortunately, an implicit breakOut would diverge.
my .02 CHFadriaan
On Fri, Oct 23, 2009 at 1:35 PM, Miles Sabin <miles@milessabin.com> wrote:
import scala.collection.generic._ import scala.collection._import scala.collection.mutable._
def breakOut[From, T, To](implicit b : CanBuildFrom[Nothing, T, To]) = new CanBuildFrom[From, T, To] { def apply(from: From) = b.apply() ; def apply() = b.apply() }
scala> val l = List(1, 2, 3)l: List[Int] = List(1, 2, 3)
scala> val a: Array[Int] = l.map(_ + 1)(breakOut) a: Array[Int] = Array(2, 3, 4)
Unfortunately, an implicit breakOut would diverge.
my .02 CHFadriaan
On Fri, Oct 23, 2009 at 1:35 PM, Miles Sabin <miles@milessabin.com> wrote:
Suppose I have a List whose elements I want to transform, and collect
in an Array.
The new Builder/CanBuildFrom mechanism should make it easy to do this
without constructing an intermediate List, but currently the standard
library doesn't make it particularly obvious how to do it (at least,
if it does, I've missed it).
I think we should do something to make this more straightforward.
It ought to be possible to allow a Builder to act as it's own factory.
The obvious implicit doesn't play all that nicely with type inference,
implicit def builderIsBuilderFactory[From, T, To](b : Builder[T, To]) =
new CanBuildFrom[From, T, To] {
def apply(from: From) = b ; def apply() = b
}
scala> val l = List(1, 2, 3)
l: List[Int] = List(1, 2, 3)
scala> val a = l.map(_ + 1)(Array.newBuilder[Int]) <-- Type param required
a: Array[Int] = Array(2, 3, 4)
scala> val l2 = a.map(_ + 1)(List.newBuilder[Int]) <-- Type param required
l2: List[Int] = List(3, 4, 5)
Making the implicit explicit isn't so bad,
def buildWith[From, T, To](b : Builder[T, To]) =
new CanBuildFrom[From, T, To] {
def apply(from: From) = b ; def apply() = b
}
scala> val l = List(1, 2, 3)
l: List[Int] = List(1, 2, 3)
scala> val a = l.map(_ + 1)(buildWith(Array.newBuilder))
a: Array[Int] = Array(2, 3, 4)
scala> val l2 = a.map(_ + 1)(buildWith(List.newBuilder))
l2: List[Int] = List(3, 4, 5)
But maybe we can do better ... could Builder extend CanBuildFrom in a
way which would allow,
val a = l.map(_ + 1)(Array.newBuilder)
val l2 = a.map(_ + 1)(List.newBuilder)
without either an explicit type parameter or function application?
Thoughts?
Cheers,
Miles
--
Miles Sabin
tel: +44 (0)7813 944 528
skype: milessabin
http://www.chuusai.com/
http://twitter.com/milessabin
Disclaimer: http://www.kuleuven.be/cwis/email_disclaimer.htm
Fri, 2009-10-23, 14:37
#3
Re: Support for explicit Builders
On Fri, Oct 23, 2009 at 2:12 PM, Adriaan Moors
wrote:
> I agree this would be useful (in our OOPSLA paper we called this mapOut).
> With the current library as a given, I can't think of a better/shorter way
> to do it than:
> scala> val a: Array[Int] = l.map(_ + 1)(breakOut)
> a: Array[Int] = Array(2, 3, 4)
OK, that's unexpectedly terse :-)
> Unfortunately, an implicit breakOut would diverge.
That's a bit of a shame ... having this driven entirely by the type
annotation without the explicit builder would be fantastic.
Cheers,
Miles
On Fri, Oct 23, 2009 at 9:35 AM, Miles Sabin <miles@milessabin.com> wrote:
--
Daniel C. Sobral
Something I learned in academia: there are three kinds of academic reviews: review by name, review by reference and review by value.