0
\$\begingroup\$

I need to simply count lines of Scala code in a project, which includes some package(i.e. directory) hierarchy.

I'm not sure about the performance of the code below. Can you help improve it, if possible?

Also, in Java, we have reduce() in the Stream API, and I didn't find its counterpart in the Scala library, so ended with foldLeft().

import java.io.File
import scala.io.Source

object CountLoc {
  def main(args: Array[String]): Unit = {
    val parentDir: File = new File(System.getProperty("user.dir"))

    def traverse(dir: File): Int = {
      val all = dir.list().map(f => new File(dir.getAbsolutePath + "/" + f))
      val srcs = all.filter(!_.isDirectory).filter(_.getName.endsWith(".scala"))
      val dirs = all.filter(_.isDirectory)
      srcs.foldLeft(0)((i, f) => i + Source.fromFile(f).getLines().filterNot(_.isEmpty).toList.size) +
        dirs.toList.foldLeft(0)((i,d) => i + traverse(d))
    }

    println("LOC: " + traverse(parentDir))
  }
}
\$\endgroup\$
  • 1
    \$\begingroup\$ Why are you defining a function inside of a function? That's not a good idea for performance. \$\endgroup\$ – FreezePhoenix Aug 14 '18 at 19:26
0
\$\begingroup\$

Instead of collecting all the source files in one sweep, and all the sub-directories in another sweep, you could move the foldLeft() to the top level and deal with each element as it is encountered.

def traverse(dir :File) :Int =
  dir.listFiles().foldLeft(0){ case (sum,file) =>
    if (file.isDirectory)
      sum + traverse(file)
    else if (file.getName.endsWith(".scala"))
      sum + io.Source.fromFile(file).getLines().count(_.nonEmpty)
    else
      sum
  }
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.