This page is no longer maintained — Please continue to the home page at www.scala-lang.org

Re: Folding fun

No replies
Joshua.Suereth
Joined: 2008-09-02,
User offline. Last seen 32 weeks 5 days ago.
haha, I mean benchmarks....

On Thu, Dec 1, 2011 at 1:06 PM, Josh Suereth <joshua [dot] suereth [at] gmail [dot] com> wrote:
no.
The return expression for the method is the foldLeft call.  The tail-call is *inside* the fold, and so it regular recursion.

As I stated earlier, you could use a Traversable[File] that uses tail-recurssion to iterate files and then use a 'view' to lazily iterate/filter and early-exit.   It's fast and efificent (at least according to all my bookmarks).
Plus, the code should be easier to read/maintain in the future :)
- Josh

On Thu, Dec 1, 2011 at 12:17 PM, Eric Kolotyluk <eric [dot] kolotyluk [at] gmail [dot] com> wrote:
Thanks :-)

Yes, foldLeft works much better. I think I had one of those brain farts where I wrote "fold" but was reading the scaladoc for "foldLeft" - the lesson is, stop working on a problem at the end of the day when you are too tired to read properly %-)

I reorganize the code so it bails out early as I intended. It seems to work correctly in testing. Now to explore some better ways to code the same functionality. This code appears to to check the file system one more time than it needs to. Also, handling Option really seems to complicate the code, but I needed to deal with the case when there are no files to be found.

Question: in my example below, would the compiler be able to do tail recursion optimization?

Cheers, Eric

  /**
   * Return true if time is newer than any source files
   */
  def newer(time:Long, sourceName : String) : Boolean = {
    def newerOption(sourceName : String) : Option[Boolean] = {
      val sourceFile = new File(sourceName)
      if (sourceFile.isDirectory())
        sourceFile.list.foldLeft(Option.empty[Boolean]) {(result, name) =>
          val sourcePath = sourceName + File.separator + name
          result match {
            case None => newerOption(sourcePath)
            case Some(boolean1) => {
              def boolean3 = newerOption(sourcePath) match {
                case None => boolean1
                case Some(boolean2) => boolean2
              }
              Some(boolean1 || boolean3)
            }
          }
        }
      else
        Some(sourceName.endsWith(".scala") && sourceFile.lastModified() < time)
    }
    newerOption(sourceName).getOrElse(true)
  }


On 2011-11-30 11:55 PM, Som Snytt wrote:

Did you intend to foldLeft?

def fold [A1 >: T] (z: A1)(op: (A1, A1) ⇒ A1): A1
def foldLeft [B] (z: B)(op: (B, T) ⇒ B): B

scala> f.list.fold(Option.empty[Boolean]) {(a,b) => Option(true)}
res6: java.io.Serializable = Some(true)

Serializable is the A1, since your z is an Option and the T is String.
foldLeft means the start value and the result is a B, different from T.

On Wed, Nov 30, 2011 at 7:02 PM, Eric Kolotyluk <eric [dot] kolotyluk [at] gmail [dot] com> wrote:
I have the following code

  /**
   * Return true if time is newer than any source files
   */
  def newer(time:Long, sourceName : String) : Boolean = {
    def newerOption(sourceName : String) : Option[Boolean] = {
      val sourceFile = new File(sourceName)
      if (sourceFile.isDirectory())
        sourceFile.list.fold(Option.empty[Boolean]) {(result, name) =>
          val sourcePath = sourceName + File.separator + name
          result match {
            case None => newerOption(sourcePath)
            case Some(boolean1:Boolean) =>
              newerOption(sourcePath) match {
                case None => result
                case Some(boolean2:Boolean) => Some(boolean1 || boolean2)
              }
          }
        }
      else
        Some(sourceName.endsWith(".scala") && sourceFile.lastModified() < time)
    }
    newerOption(sourceName).getOrElse(true)
  }

with the following error

error: type mismatch;
 found   : java.io.Serializable
 required: Option[Boolean]
        sourceFile.list.fold(Option.empty[Boolean]) {(result, name) =>
                                                    ^

but I cannot understand what the problem is. Could someone please help me out.

Is it possible to make the diagnostics more clear on what the compiler is complaining about?

Cheers, Eric



Copyright © 2012 École Polytechnique Fédérale de Lausanne (EPFL), Lausanne, Switzerland