Nil.par.reduceLeft should throw UnsupportedOperationException, not NoSuchElementException
retronym opened this issue · comments
% scala --scala-version 2.13.3 -Corg.scala-lang.modules::scala-parallel-collections:1.0.0-RC1
Welcome to Scala 2.13.3 (OpenJDK 64-Bit Server VM, Java 14.0.1).
Type in expressions for evaluation. Or try :help.
scala> List.empty[String].reduce(_ + _)
java.lang.UnsupportedOperationException: empty.reduceLeft
at scala.collection.IterableOnceOps.reduceLeft(IterableOnce.scala:723)
at scala.collection.IterableOnceOps.reduceLeft$(IterableOnce.scala:720)
at scala.collection.AbstractIterable.reduceLeft(Iterable.scala:920)
at scala.collection.IterableOnceOps.reduce(IterableOnce.scala:692)
at scala.collection.IterableOnceOps.reduce$(IterableOnce.scala:692)
at scala.collection.AbstractIterable.reduce(Iterable.scala:920)
... 32 elided
scala> import scala.collection.parallel.CollectionConverters._
import scala.collection.parallel.CollectionConverters._
scala> List.empty[String].par.reduce(_ + _)
java.util.NoSuchElementException: None.get
at scala.None$.get(Option.scala:627)
at scala.None$.get(Option.scala:626)
at scala.collection.parallel.ParIterableLike.reduce(ParIterableLike.scala:361)
at scala.collection.parallel.ParIterableLike.reduce$(ParIterableLike.scala:360)
at scala.collection.parallel.immutable.ParVector.reduce(ParVector.scala:40)
... 32 elided
Nil.par.min
and Nil.par.max
may have the same issue.
I have used "org.scala-lang.modules" %% "scala-parallel-collections" % "1.0.1"
.
root@9d686781776b:/opt/scala-parallel-collections/sandbox# sbt
[info] welcome to sbt 1.4.3 (AdoptOpenJDK Java 11.0.9.1)
[info] loading project definition from /opt/scala-parallel-collections/sandbox/project
[info] loading settings for project sandbox from build.sbt ...
[info] set current project to sandbox (in build file:/opt/scala-parallel-collections/sandbox/)
[info] sbt server started at local:///root/.sbt/1.0/server/ac048f6b25b988f0e872/sock
[info] started sbt server
sbt:sandbox> console
[info] Starting scala interpreter...
Welcome to Scala 2.13.5 (OpenJDK 64-Bit Server VM, Java 11.0.9.1).
Type in expressions for evaluation. Or try :help.
scala> import scala.collection.parallel.CollectionConverters._
import scala.collection.parallel.CollectionConverters._
scala> List.empty[Int].min
java.lang.UnsupportedOperationException: empty.min
at scala.collection.IterableOnceOps.min(IterableOnce.scala:914)
at scala.collection.IterableOnceOps.min$(IterableOnce.scala:912)
at scala.collection.AbstractIterable.min(Iterable.scala:919)
... 35 elided
scala> List.empty[Int].par.min
java.util.NoSuchElementException: None.get
at scala.None$.get(Option.scala:627)
at scala.None$.get(Option.scala:626)
at scala.collection.parallel.ParIterableLike.min(ParIterableLike.scala:466)
at scala.collection.parallel.ParIterableLike.min$(ParIterableLike.scala:465)
at scala.collection.parallel.immutable.ParVector.min(ParVector.scala:40)
... 35 elided
scala> List.empty[Int].max
java.lang.UnsupportedOperationException: empty.max
at scala.collection.IterableOnceOps.max(IterableOnce.scala:945)
at scala.collection.IterableOnceOps.max$(IterableOnce.scala:943)
at scala.collection.AbstractIterable.max(Iterable.scala:919)
... 35 elided
scala> List.empty[Int].par.max
java.util.NoSuchElementException: None.get
at scala.None$.get(Option.scala:627)
at scala.None$.get(Option.scala:626)
at scala.collection.parallel.ParIterableLike.max(ParIterableLike.scala:470)
at scala.collection.parallel.ParIterableLike.max$(ParIterableLike.scala:469)
at scala.collection.parallel.immutable.ParVector.max(ParVector.scala:40)
... 35 elided
But, Nil.par.minBy
and Nil.par.maxBy
don't have.
scala> List.empty[String].minBy(_.length)
java.lang.UnsupportedOperationException: empty.minBy
at scala.collection.IterableOnceOps.minBy(IterableOnce.scala:1025)
at scala.collection.IterableOnceOps.minBy$(IterableOnce.scala:1023)
at scala.collection.AbstractIterable.minBy(Iterable.scala:919)
... 35 elided
scala> List.empty[String].par.minBy(_.length)
java.lang.UnsupportedOperationException: empty.minBy
at scala.collection.parallel.ParIterableLike.minBy(ParIterableLike.scala:480)
at scala.collection.parallel.ParIterableLike.minBy$(ParIterableLike.scala:479)
at scala.collection.parallel.immutable.ParVector.minBy(ParVector.scala:40)
... 35 elided
scala> List.empty[String].maxBy(_.length)
java.lang.UnsupportedOperationException: empty.maxBy
at scala.collection.IterableOnceOps.maxBy(IterableOnce.scala:978)
at scala.collection.IterableOnceOps.maxBy$(IterableOnce.scala:976)
at scala.collection.AbstractIterable.maxBy(Iterable.scala:919)
... 35 elided
scala> List.empty[String].par.maxBy(_.length)
java.lang.UnsupportedOperationException: empty.maxBy
at scala.collection.parallel.ParIterableLike.maxBy(ParIterableLike.scala:474)
at scala.collection.parallel.ParIterableLike.maxBy$(ParIterableLike.scala:473)
at scala.collection.parallel.immutable.ParVector.maxBy(ParVector.scala:40)
... 35 elided
maxBy
throws UnsupportedOperationException
if a collection is empty 😄 .
def maxBy[S](f: T => S)(implicit cmp: Ordering[S]): T = { if (isEmpty) throw new UnsupportedOperationException("empty.maxBy") reduce((x, y) => if (cmp.gteq(f(x), f(y))) x else y) }
reduce
does not 😢 .
tasksupport.executeAndWaitResult(new Reduce(op, splitter))
produces None
if a collection is empty.
Then, None.get
throws NoSuchElementException
.
def reduce[U >: T](op: (U, U) => U): U = { tasksupport.executeAndWaitResult(new Reduce(op, splitter)).get }
IMO, it would be nice to check whether a collection is empty or not at first in the reduce
function.
FYI, scala.collection.IterableOnce
also does.
https://github.com/scala/scala/blob/2.13.x/src/library/scala/collection/IterableOnce.scala#L724-L741
def reduceLeft[B >: A](op: (B, A) => B): B = { val it = iterator if (it.isEmpty) throw new UnsupportedOperationException("empty.reduceLeft") //...
I attempt to resolve this issue at #167 😃