Sunday, January 20, 2008

Scala: Fold Left Question

I recently realized that I could make a piece of code I posted in a recent blog much cleaner using foldLeft. I have a bit of a problem however, the code is in a very performance sensitive area and I should break out of the fold whenever I encounter a certain condition. To the best of my knowledge foldLeft has no way to break out. It just folds all the way and you get your result at the finish. This is a bit unfortunate. Is there a way to break out and still keep the code clean?

Here is my example, old code first. A PowerSource is on if any of its incoming power sources are on.


private def updateOnOff = {
def calculateOnOff: boolean = {
incomingPowerSources.foreach( p => {if( p.isOn ) return true; })
return false;
}
val newOnOff = calculateOnOff
if( cachedOnOffBoolean != newOnOff ){
cachedOnOffBoolean = newOnOff
notifyConnections;
}
}


Here is the new code using foldLeft.


private def updateOnOff = {
val newOnOff = incomingPowerSources.foldLeft( false )(_||_.isOn);
if( cachedOnOffBoolean != newOnOff ){
cachedOnOffBoolean = newOnOff
notifyConnections;
}
}


The new code is far nicer than the old code. I've decided I'm going to go with it. In most cases PowerSources have only one direct input. Some have two, like OrGate, but for now I'm going to see what kind of performance hit I get.

Now, if only I had a performance testing framework in Scala. Does anyone know of one?

6 comments:

  1. Can you not just use find instead of foldLeft? I believe find will return the first time it hits a predicate that matches. find documentation. foldLeft will operate in O(n) time so you should be able to do better.

    ReplyDelete
  2. Done!

    private def updateOnOff = {
    val newOnOff = incomingPowerSources.find(x => x.isOn).isDefined
    if( cachedOnOffBoolean != newOnOff ){
    cachedOnOffBoolean = newOnOff
    notifyConnections;
    }
    }


    Thanks a lot! I'm still learning the API, but thats probably something I should have seen.

    ReplyDelete
  3. I also changed it slightly to be:

    private def updateOnOff = {
    val newOnOff = incomingPowerSources.find(_.isOn).isDefined
    if( cachedOnOffBoolean != newOnOff ){
    cachedOnOffBoolean = newOnOff
    notifyConnections;
    }
    }

    Which is a little nicer.

    ReplyDelete
  4. Ah, point free style is nice. I'm only just starting to learn Scala also, and am finding the API docs a little hard to read after relying on good tool support (IntelliJ) for so long in Java.

    ReplyDelete
  5. They are definitely taking a bit to get used to. Thanks for your help.

    Can I ask how you found this so fast? I just posted it a little while ago.

    ReplyDelete
  6. Umm, maybe it was Google blog search??? I don't remember sorry, I read a fair bit of stuff each day. I do use the blog searcht a fair bit though, I get RSS notifications when stuff is indexed by Google.

    ReplyDelete