-
Notifications
You must be signed in to change notification settings - Fork 21
List.foldRight throws StackOverflowError #2818
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
Imported From: https://issues.scala-lang.org/browse/SI-2818?orig=1 |
@hubertp said: scala> (List.range(1, 1000000) :\ 0) (_ + _)
java.lang.StackOverflowError
at scala.collection.LinearSeqLike$$class.foldRight(LinearSeqLike.scala:167)
at scala.collection.immutable.List.foldRight(List.scala:46)
at scala.collection.LinearSeqLike$$class.foldRight(LinearSeqLike.scala:168)
at scala.collection.immutable.List.foldRight(List.scala:46)
at scala.collection.LinearSeqLike$$class.foldRight(LinearSeqLike.scala:168)
at scala.collection.immutable.List.foldRight(List.scala:46)
at scala.collection.LinearSeqLike$$class.foldRight(LinearSeqLike.scala:168)
at scala.collection.immutable.List.foldRight(List.scala:46)
at scala.collection.LinearSeqLike$$class.foldRight(LinearSeqLike.scala:168)
at scala.collection.immutable.List.foldRight(List.scala:46)
at scala.collection.LinearSeqLike$$class.foldRight(LinearSeqLike.scala:168)
at scala.collection.immutable.List.foldRight(List.scala:46)
at scala.collection.LinearSeqLike$$class.foldRight(LinearSeqLike.scala:168) |
@lrytz said: |
johnconnor said: def foldRight[B](z: B)(f: (A, B) => B): B = {
val STACK_DEPTH_LIMIT = 100
def revArgs[A1, A2, C](f: (A1, A2) => C): ((A2, A1) => C) =
(x: A2, y: A1) => f (y, x)
def aux(iterCnt: Int, ls: Lst[A]): B = ls match {
case Nil => z
case x :: xs => {
if (iterCnt < STACK_DEPTH_LIMIT) {
f(x, aux(iterCnt + 1, xs))
}
else {
val revRest = ls reverse
val g = revArgs(f)
revRest.foldLeft(z)(g)
}
}
}
aux(0, this)
} |
NagMacFeegle (nagmacfeegle) said: The STACK_DEPTH_LIMIT should not be too big, because you never know where you are in the stack, but 100 seems reasonable. Since List#reverse is linear in list size, as is foldLeft, it would probably make the implementation more elegant if "reverse" would always be used and the "small list" case would not be considered, without making it unreasonably slower. |
@odersky said: |
Sean Parsons (seanparsons) said: It seems sensible that List.foldRight can be implemented simply at virtually no penalty to performance (caliper based benchmarks linked in the discussion above) in the smaller cases if implemented as follows: override def foldRight[B](z: B)(op: (A, B) => B): B = {
if (lengthCompare(10) < 0) // MAX_DEPTH=10
super.foldRight(z)(op)
else
reverse.foldLeft(z)((right, left) => op(left, right))
} This mitigates the case where a callee unwittingly does a foldRight on a type with the signature of Seq[User] for example which is actually a List. |
Sean Parsons (seanparsons) said: |
@Blaisorblade said:
|
@adriaanm said: |
@JamesIry said: |
@SethTisue said: |
@Blaisorblade said: |
List.foldRight is not tail recursive, so it throws StackOverflowError when called on a large list.
Example:
In fact, 10000 is enough on my system.
The text was updated successfully, but these errors were encountered: