Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using partially applied functions, performance issue

Tags:

scala

object E7 {
  def next_prime(primes: List[Int]) = primes match {
    case ps@(h :: t) => {


      // Version 1
      val rpq = ps.reverse.exists _

      // Version 2
      val rpq = ps.reverse.exists(_)


      (Iterator.from(h + 1).find((v) => ! rpq(v % _ == 0)): @unchecked) match {
        case Some(v) => v :: ps
      }
    }
    case Nil    => List(2)
  }

  val primes = Iterator.iterate(List[Int]())(next_prime)

  def main(args: Array[String]) {
    println(primes.drop(20001).next.head)
  }
}

First version takes 3.6s to complete, second - 19.3s! What's the difference?

Edit: Scala version 2.9.2 (Java HotSpot(TM) 64-Bit Server VM, Java 1.7.0_21)

like image 325
Victor Moroz Avatar asked Oct 04 '22 00:10

Victor Moroz


1 Answers

The first one is interpreted as

{ val temp = ps.reverse; (x: Int) => temp.exists(x) }

while the second one is interpreted as

(x: Int) => ps.reverse.exists(x)

This explains the difference: you have to reverse each time in the second case, but only once in the first. I am not sure where in the spec it says that this is what you get in each case (or if it does).

like image 163
Rex Kerr Avatar answered Oct 10 '22 05:10

Rex Kerr