This page is no longer maintained — Please continue to the home page at www.scala-lang.org

Support for explicit Builders

3 replies
milessabin
Joined: 2008-08-11,
User offline. Last seen 33 weeks 3 days ago.

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

dcsobral
Joined: 2009-04-23,
User offline. Last seen 38 weeks 5 days ago.
Re: Support for explicit Builders
Such a thing didn't occur to me, but it certainly beats calling toList or toArray afterwards?

On Fri, Oct 23, 2009 at 9:35 AM, 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



--
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.
Adriaan Moors
Joined: 2009-04-03,
User offline. Last seen 42 years 45 weeks ago.
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:
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

milessabin
Joined: 2008-08-11,
User offline. Last seen 33 weeks 3 days ago.
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

Copyright © 2012 École Polytechnique Fédérale de Lausanne (EPFL), Lausanne, Switzerland