Skip to content

Commit 8ed13e5

Browse files
authored
Merge pull request scala/scala#10230 from som-snytt/tweak/isEmpty-knownSize
IterableOnce.isEmpty uses knownSize, sum is reduce
2 parents ccf3af2 + f9c6848 commit 8ed13e5

File tree

2 files changed

+32
-8
lines changed

2 files changed

+32
-8
lines changed

library/src/scala/collection/IterableOnce.scala

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -843,7 +843,12 @@ trait IterableOnceOps[+A, +CC[_], +C] extends Any { this: IterableOnce[A] =>
843843
*
844844
* @return `true` if the $coll contains no elements, `false` otherwise.
845845
*/
846-
def isEmpty: Boolean = !iterator.hasNext
846+
def isEmpty: Boolean =
847+
knownSize match {
848+
case -1 => !iterator.hasNext
849+
case 0 => true
850+
case _ => false
851+
}
847852

848853
/** Tests whether the $coll is not empty.
849854
*
@@ -929,7 +934,9 @@ trait IterableOnceOps[+A, +CC[_], +C] extends Any { this: IterableOnce[A] =>
929934
i - start
930935
}
931936

932-
/** Sums up the elements of this collection.
937+
/** Sums the elements of this collection.
938+
*
939+
* The default implementation uses `reduce` for a known non-empty collection, `foldLeft` otherwise.
933940
*
934941
* $willNotTerminateInf
935942
*
@@ -940,12 +947,14 @@ trait IterableOnceOps[+A, +CC[_], +C] extends Any { this: IterableOnce[A] =>
940947
*/
941948
def sum[B >: A](implicit num: Numeric[B]): B =
942949
knownSize match {
943-
case -1 => reduceLeftIterator[B](num.zero)(num.plus)
950+
case -1 => foldLeft(num.zero)(num.plus)
944951
case 0 => num.zero
945952
case _ => reduce(num.plus)
946953
}
947954

948-
/** Multiplies up the elements of this collection.
955+
/** Multiplies together the elements of this collection.
956+
*
957+
* The default implementation uses `reduce` for a known non-empty collection, `foldLeft` otherwise.
949958
*
950959
* $willNotTerminateInf
951960
*
@@ -956,7 +965,7 @@ trait IterableOnceOps[+A, +CC[_], +C] extends Any { this: IterableOnce[A] =>
956965
*/
957966
def product[B >: A](implicit num: Numeric[B]): B =
958967
knownSize match {
959-
case -1 => reduceLeftIterator[B](num.one)(num.times)
968+
case -1 => foldLeft(num.one)(num.times)
960969
case 0 => num.one
961970
case _ => reduce(num.times)
962971
}

library/src/scala/math/Numeric.scala

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -177,9 +177,20 @@ object Numeric {
177177
implicit object DoubleIsFractional extends DoubleIsFractional with Ordering.Double.IeeeOrdering
178178

179179
trait BigDecimalIsConflicted extends Numeric[BigDecimal] {
180-
def plus(x: BigDecimal, y: BigDecimal): BigDecimal = x + y
181-
def minus(x: BigDecimal, y: BigDecimal): BigDecimal = x - y
182-
def times(x: BigDecimal, y: BigDecimal): BigDecimal = x * y
180+
// works around pollution of math context by ignoring identity element
181+
def plus(x: BigDecimal, y: BigDecimal): BigDecimal = {
182+
import BigDecimalIsConflicted._0
183+
if (x eq _0) y else x + y
184+
}
185+
def minus(x: BigDecimal, y: BigDecimal): BigDecimal = {
186+
import BigDecimalIsConflicted._0
187+
if (x eq _0) -y else x - y
188+
}
189+
// works around pollution of math context by ignoring identity element
190+
def times(x: BigDecimal, y: BigDecimal): BigDecimal = {
191+
import BigDecimalIsConflicted._1
192+
if (x eq _1) y else x * y
193+
}
183194
def negate(x: BigDecimal): BigDecimal = -x
184195
def fromInt(x: Int): BigDecimal = BigDecimal(x)
185196
def parseString(str: String): Option[BigDecimal] = Try(BigDecimal(str)).toOption
@@ -188,6 +199,10 @@ object Numeric {
188199
def toFloat(x: BigDecimal): Float = x.floatValue
189200
def toDouble(x: BigDecimal): Double = x.doubleValue
190201
}
202+
private object BigDecimalIsConflicted {
203+
private val _0 = BigDecimal(0) // cached zero is ordinarily cached for default math context
204+
private val _1 = BigDecimal(1) // cached one is ordinarily cached for default math context
205+
}
191206

192207
trait BigDecimalIsFractional extends BigDecimalIsConflicted with Fractional[BigDecimal] {
193208
def div(x: BigDecimal, y: BigDecimal): BigDecimal = x / y

0 commit comments

Comments
 (0)