Kevin Meredith
Kevin Meredith

Reputation: 41899

Non-strict Evaluation of Option[Boolean]

Given a List[Foo], I apply a function f.

def f(foo: Foo): Option[Boolean]

I wrote this function body to see if any Foo evaluates to Some(true).

val optFalse: Option[Boolean] = Some(false)
val foos: List[Foo] = ... 

foos.foldLeft(optFalse){ 
     (acc: Option[Boolean], elem: Foo) => {
        val isMatch: Option[Boolean] = f(elem)
        optionOr(acc)(match) // takes 2 Option[Boolean] and `or`'s them.
     }
}

However, the f method could be an expensive operation. I'd prefer to "short-circuit":

foos.foldLeft(optFalse){ 
     (acc: Option[Boolean], elem: Foo) => {
        if( isTrueOption(acc) ) acc
        else {
         val isMatch: Option[Boolean] = f(elem)
         isMatch
        }        
     }
}

Is there a non-strict way to fold over the entire List[Foo], but stop evaluation once one of the Option[Boolean] equals Some(true) without my changed code? Perhaps using the => operator?

If so, I'm thinking that there's a "space" cost, but I'm not entirely understanding it. Please include that topic as well in your answer (if there is one).

Upvotes: 0

Views: 105

Answers (2)

Dima
Dima

Reputation: 40500

Is this what you are looking for?

foos.reduce { 
     case (Some(true), _)=> Some(true)
     case (_, x) => f(x)
}

Upvotes: 0

lmm
lmm

Reputation: 17431

It's unclear what role Option is playing in your code. If you just want to find out whether there's any value for which f returns Some(true), that sounds like a good use case for exists, which is short-circuit:

foos.exists{x => Some(true) == f(x)}

If you need to know whether any f returns None, then clearly you'll need to evaluate the whole list (at least in the case where they're actually all Some, which is presumably the interesting case).

If it has to be a fold, then fold is strict (it would be possible to write a non-strict fold, but that wouldn't be the standard fold). You could use @Peter's solution in a more structured way by using breakable.

Upvotes: 1

Related Questions