Skip to content

Commit

Permalink
Optimization of Predef implicits.
Browse files Browse the repository at this point in the history
All those wildcards in a default-scoped implicit are expensive,
they each lead to a typevar on every search.  Restructured the
Tuple2/Tuple3 Zipped classes, they're better this way anyway.
This also gets all that Tuple[23] code out of genprod.
  • Loading branch information
paulp committed Apr 30, 2012
1 parent 94c63f5 commit cf18d87
Show file tree
Hide file tree
Showing 12 changed files with 364 additions and 522 deletions.
224 changes: 1 addition & 223 deletions src/build/genprod.scala
Original file line number Diff line number Diff line change
Expand Up @@ -256,10 +256,7 @@ class Function(val i: Int) extends Group("Function") with Arity {
zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz */

object Tuple {
val zipImports = """
import scala.collection.{ TraversableLike => TLike, IterableLike => ILike }
import scala.collection.generic.{ CanBuildFrom => CBF }
"""
val zipImports = ""

def make(i: Int) = apply(i)()
def apply(i: Int) = i match {
Expand All @@ -285,230 +282,11 @@ object TupleTwo extends Tuple(2)
* second element is the first element of this Tuple.
*/
def swap: Tuple2[T2,T1] = Tuple2(_2, _1)
@deprecated("Use `zipped` instead.", "2.9.0")
def zip[Repr1, El1, El2, To](implicit w1: T1 => TLike[El1, Repr1],
w2: T2 => Iterable[El2],
cbf1: CBF[Repr1, (El1, El2), To]): To = {
zipped map ((x, y) => ((x, y)))
}
/** Wraps a tuple in a `Zipped`, which supports 2-ary generalisations of `map`, `flatMap`, `filter`, etc.
* Note that there must be an implicit value to convert this tuple's types into a [[scala.collection.TraversableLike]]
* or [[scala.collection.IterableLike]].
* {{{
* scala> val tuple = (List(1,2,3),List('a','b','c'))
* tuple: (List[Int], List[Char]) = (List(1, 2, 3),List(a, b, c))
*
* scala> tuple.zipped map { (x,y) => x + ":" + y }
* res6: List[java.lang.String] = List(1:a, 2:b, 3:c)
* }}}
*
* @see Zipped
* Note: will not terminate for infinite-sized collections.
*/
def zipped[Repr1, El1, Repr2, El2](implicit w1: T1 => TLike[El1, Repr1], w2: T2 => ILike[El2, Repr2]): Zipped[Repr1, El1, Repr2, El2]
= new Zipped[Repr1, El1, Repr2, El2](_1, _2)
class Zipped[+Repr1, +El1, +Repr2, +El2](coll1: TLike[El1, Repr1], coll2: ILike[El2, Repr2]) { // coll2: ILike for filter
def map[B, To](f: (El1, El2) => B)(implicit cbf: CBF[Repr1, B, To]): To = {
val b = cbf(coll1.repr)
b.sizeHint(coll1)
val elems2 = coll2.iterator
for (el1 <- coll1) {
if (elems2.hasNext)
b += f(el1, elems2.next)
else
return b.result
}
b.result
}
def flatMap[B, To](f: (El1, El2) => TraversableOnce[B])(implicit cbf: CBF[Repr1, B, To]): To = {
val b = cbf(coll1.repr)
val elems2 = coll2.iterator
for (el1 <- coll1) {
if (elems2.hasNext)
b ++= f(el1, elems2.next)
else
return b.result
}
b.result
}
def filter[To1, To2](f: (El1, El2) => Boolean)(implicit cbf1: CBF[Repr1, El1, To1], cbf2: CBF[Repr2, El2, To2]): (To1, To2) = {
val b1 = cbf1(coll1.repr)
val b2 = cbf2(coll2.repr)
val elems2 = coll2.iterator
for (el1 <- coll1) {
if (elems2.hasNext) {
val el2 = elems2.next
if (f(el1, el2)) {
b1 += el1
b2 += el2
}
}
else return (b1.result, b2.result)
}
(b1.result, b2.result)
}
def exists(f: (El1, El2) => Boolean): Boolean = {
val elems2 = coll2.iterator
for (el1 <- coll1) {
if (elems2.hasNext) {
if (f(el1, elems2.next))
return true
}
else return false
}
false
}
def forall(f: (El1, El2) => Boolean): Boolean =
!exists((x, y) => !f(x, y))
def foreach[U](f: (El1, El2) => U): Unit = {
val elems2 = coll2.iterator
for (el1 <- coll1) {
if (elems2.hasNext)
f(el1, elems2.next)
else
return
}
}
}
"""
}

object TupleThree extends Tuple(3) {
override def imports = Tuple.zipImports
override def moreMethods = """
@deprecated("Use `zipped` instead.", "2.9.0")
def zip[Repr1, El1, El2, El3, To](implicit w1: T1 => TLike[El1, Repr1],
w2: T2 => Iterable[El2],
w3: T3 => Iterable[El3],
cbf1: CBF[Repr1, (El1, El2, El3), To]): To = {
zipped map ((x, y, z) => ((x, y, z)))
}
/** Wraps a tuple in a `Zipped`, which supports 3-ary generalisations of `map`, `flatMap`, `filter`, etc.
* Note that there must be an implicit value to convert this tuple's types into a [[scala.collection.TraversableLike]]
* or [[scala.collection.IterableLike]].
* {{{
* scala> val tuple = (List(1,2,3),List('a','b','c'),List("x","y","z"))
* tuple: (List[Int], List[Char], List[java.lang.String]) = (List(1, 2, 3),List(a, b, c),List(x, y, z))
*
* scala> tuple.zipped map { (x,y,z) => x + ":" + y + ":" + z}
* res8: List[java.lang.String] = List(1:a:x, 2:b:y, 3:c:z)
* }}}
*
* @see Zipped
* Note: will not terminate for infinite-sized collections.
*/
def zipped[Repr1, El1, Repr2, El2, Repr3, El3](implicit w1: T1 => TLike[El1, Repr1],
w2: T2 => ILike[El2, Repr2],
w3: T3 => ILike[El3, Repr3]): Zipped[Repr1, El1, Repr2, El2, Repr3, El3]
= new Zipped[Repr1, El1, Repr2, El2, Repr3, El3](_1, _2, _3)
class Zipped[+Repr1, +El1, +Repr2, +El2, +Repr3, +El3](coll1: TLike[El1, Repr1],
coll2: ILike[El2, Repr2],
coll3: ILike[El3, Repr3]) {
def map[B, To](f: (El1, El2, El3) => B)(implicit cbf: CBF[Repr1, B, To]): To = {
val b = cbf(coll1.repr)
val elems2 = coll2.iterator
val elems3 = coll3.iterator
for (el1 <- coll1) {
if (elems2.hasNext && elems3.hasNext)
b += f(el1, elems2.next, elems3.next)
else
return b.result
}
b.result
}
def flatMap[B, To](f: (El1, El2, El3) => TraversableOnce[B])(implicit cbf: CBF[Repr1, B, To]): To = {
val b = cbf(coll1.repr)
val elems2 = coll2.iterator
val elems3 = coll3.iterator
for (el1 <- coll1) {
if (elems2.hasNext && elems3.hasNext)
b ++= f(el1, elems2.next, elems3.next)
else
return b.result
}
b.result
}
def filter[To1, To2, To3](f: (El1, El2, El3) => Boolean)(
implicit cbf1: CBF[Repr1, El1, To1],
cbf2: CBF[Repr2, El2, To2],
cbf3: CBF[Repr3, El3, To3]): (To1, To2, To3) = {
val b1 = cbf1(coll1.repr)
val b2 = cbf2(coll2.repr)
val b3 = cbf3(coll3.repr)
val elems2 = coll2.iterator
val elems3 = coll3.iterator
def result = (b1.result, b2.result, b3.result)
for (el1 <- coll1) {
if (elems2.hasNext && elems3.hasNext) {
val el2 = elems2.next
val el3 = elems3.next
if (f(el1, el2, el3)) {
b1 += el1
b2 += el2
b3 += el3
}
}
else return result
}
result
}
def exists(f: (El1, El2, El3) => Boolean): Boolean = {
val elems2 = coll2.iterator
val elems3 = coll3.iterator
for (el1 <- coll1) {
if (elems2.hasNext && elems3.hasNext) {
if (f(el1, elems2.next, elems3.next))
return true
}
else return false
}
false
}
def forall(f: (El1, El2, El3) => Boolean): Boolean =
!exists((x, y, z) => !f(x, y, z))
def foreach[U](f: (El1, El2, El3) => U): Unit = {
val elems2 = coll2.iterator
val elems3 = coll3.iterator
for (el1 <- coll1) {
if (elems2.hasNext && elems3.hasNext)
f(el1, elems2.next, elems3.next)
else
return
}
}
}
"""
}

class Tuple(val i: Int) extends Group("Tuple") with Arity {
Expand Down
45 changes: 28 additions & 17 deletions src/compiler/scala/tools/cmd/gen/AnyVals.scala
Original file line number Diff line number Diff line change
Expand Up @@ -15,18 +15,27 @@ trait AnyValReps {

case class Op(val op : String, val doc : String)

private def companionCoercions(tos: String*) = {
private def companionCoercions(tos: AnyValRep*) = {
tos.toList map (to =>
"""implicit def %s2%s(x: %s): %s = x.to%s""".format(javaEquiv, to, name, to.capitalize, to.capitalize)
"""implicit def @javaequiv@2%s(x: @name@): %s = x.to%s""".format(to.javaEquiv, to.name, to.name)
)
}
def implicitCoercions: List[String] = javaEquiv match {
case "byte" => companionCoercions("short", "int", "long", "float", "double")
case "short" | "char" => companionCoercions("int", "long", "float", "double")
case "int" => companionCoercions("long", "float", "double")
case "long" => companionCoercions("float", "double")
case "float" => companionCoercions("double")
case _ => Nil
def coercionCommentExtra = ""
def coercionComment = """
/** Language mandated coercions from @name@ to "wider" types.%s
*/""".format(coercionCommentExtra)

def implicitCoercions: List[String] = {
val coercions = this match {
case B => companionCoercions(S, I, L, F, D)
case S | C => companionCoercions(I, L, F, D)
case I => companionCoercions(L, F, D)
case L => companionCoercions(F, D)
case F => companionCoercions(D)
case _ => Nil
}
if (coercions.isEmpty) Nil
else coercionComment :: coercions
}

def isCardinal: Boolean = isIntegerType(this)
Expand Down Expand Up @@ -174,7 +183,7 @@ trait AnyValReps {
}
def objectLines = {
val comp = if (isCardinal) cardinalCompanion else floatingCompanion
((comp + allCompanions).trim.lines map interpolate).toList ++ implicitCoercions
(comp + allCompanions + "\n" + nonUnitCompanions).trim.lines.toList ++ implicitCoercions map interpolate
}

/** Makes a set of binary operations based on the given set of ops, args, and resultFn.
Expand Down Expand Up @@ -238,8 +247,9 @@ trait AnyValReps {
def classDoc = interpolate(classDocTemplate)
def objectDoc = ""
def mkImports = ""
def mkClass = assemble("final class", "private", "AnyVal", classLines) + "\n"
def mkObject = assemble("object", "", "AnyValCompanion", objectLines) + "\n"

def mkClass = assemble("final class " + name + " private extends AnyVal", classLines)
def mkObject = assemble("object " + name + " extends AnyValCompanion", objectLines)
def make() = List[String](
headerTemplate,
mkImports,
Expand All @@ -249,11 +259,10 @@ trait AnyValReps {
mkObject
) mkString ""

def assemble(what: String, ctor: String, parent: String, lines: List[String]): String = {
val decl = "%s %s %s extends %s ".format(what, name, ctor, parent)
val body = if (lines.isEmpty) "{ }\n\n" else lines map indent mkString ("{\n", "\n", "\n}\n")
def assemble(decl: String, lines: List[String]): String = {
val body = if (lines.isEmpty) " { }\n\n" else lines map indent mkString (" {\n", "\n", "\n}\n")

decl + body
decl + body + "\n"
}
override def toString = name
}
Expand Down Expand Up @@ -310,6 +319,8 @@ def unbox(x: java.lang.Object): @name@ = @unboxImpl@
override def toString = "object scala.@name@"
"""

def nonUnitCompanions = "" // todo

def cardinalCompanion = """
/** The smallest value representable as a @name@.
*/
Expand Down Expand Up @@ -446,7 +457,7 @@ def ^(x: Boolean): Boolean = sys.error("stub")
override def getClass(): Class[Boolean] = sys.error("stub")
""".trim.lines.toList

def objectLines = interpolate(allCompanions).lines.toList
def objectLines = interpolate(allCompanions + "\n" + nonUnitCompanions).lines.toList
}
object U extends AnyValRep("Unit", None, "void") {
override def classDoc = """
Expand Down
2 changes: 1 addition & 1 deletion src/library/scala/Function0.scala
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
** |/ **
\* */
// GENERATED CODE: DO NOT EDIT.
// genprod generated these sources at: Sat Apr 28 12:59:55 PDT 2012
// genprod generated these sources at: Mon Apr 30 07:46:11 PDT 2012

package scala

Expand Down
Loading

0 comments on commit cf18d87

Please sign in to comment.