Skip to content
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

ManagedResource.map() is not stack safe #65

Open
underspecified opened this issue Jul 31, 2017 · 2 comments
Open

ManagedResource.map() is not stack safe #65

underspecified opened this issue Jul 31, 2017 · 2 comments

Comments

@underspecified
Copy link

underspecified commented Jul 31, 2017

Greetings,

I have been using scala-arm to read and concatenate lines from a large number of files, an operation that requires a large number of nested calls to ManagedResource.map(). This appears to trigger a stack overflow at somewhere between 1,000 and 10,000 nested calls. Here is a trivial reproduction:

import resource._
import scala.math.BigInt._

// calculate factorial inside of Scala Option
def factorialO(max: Int): Option[BigInt] = {
  val z: Option[BigInt] = Option(1)
  (1 to max).foldLeft(z) { (b,a) => b.map(_ * a) }
}

// calculate factorial inside of ManagedResource
def factorialR(max: Int): ManagedResource[BigInt] = {
  val z: ManagedResource[BigInt] = new ConstantManagedResource(1)
  (1 to max).foldLeft(z) { (b,a) => b.map(_ * a) }
}

// Some(93326215443944152681699238856266700490715968264381621468592963895217599993229915608941463976156518286253697920827223758251185210916864000000000000000000000000)                  
println(factorialO(100))

// 93326215443944152681699238856266700490715968264381621468592963895217599993229915608941463976156518286253697920827223758251185210916864000000000000000000000000                        
println(factorialR(100).acquireAndGet(x => x))

// prints really big number                                                                                                                                                              
println(factorialO(10000))

// java.lang.StackOverflowError                                                                                                                                                          
//println(factorialR(10000).acquireAndGet(x => x))                                                                                                                                       

It seems the solution is to define map() and flatMap() using trampolines like is done in Scala Cats, or am I missing something?

All the best,
-underspecified

@jsuereth
Copy link
Owner

Yes, we'd need to trampoline to fix this. Will leave this as an open implementation question for now. This library was not intended for such nested usage initially, but if it becomes a common use-case we must support, we can adapt to it.

@averma111
Copy link

import scala.math.BigInt
def fact(x:BigInt):BigInt={
if(x==0) 1 else x * fact(x-1)
}
fact: (x: scala.math.BigInt)scala.math.BigInt
fact(100000)

scala> fact(100000)
java.lang.StackOverflowError
at scala.math.BigInt$.apply(BigInt.scala:42)
at scala.math.BigInt$.int2bigInt(BigInt.scala:100)
at scala.math.BigInt.isValidInt(BigInt.scala:137)
at scala.math.ScalaNumericAnyConversions.unifiedPrimitiveEquals(ScalaNumericConversions.scala:117)
at scala.math.ScalaNumericAnyConversions.unifiedPrimitiveEquals$(ScalaNumericConversions.scala:113)
at scala.math.BigInt.unifiedPrimitiveEquals(BigInt.scala:114)
at scala.math.BigInt.equals(BigInt.scala:132)
at scala.runtime.BoxesRunTime.equalsNumNum(BoxesRunTime.java:170)
at scala.runtime.BoxesRunTime.equalsNumObject(BoxesRunTime.java:142)

Any solution to avoid this execption

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants