//where f is a function returning Option[Something] val t = f(args) getOrElse 3
Recently I realized (classic lightbulb moment :) that getOrElse actually takes a function as the argument:
def getOrElse [B >: A] (default: ⇒ B): B //Returns the option's value if the option is nonempty, otherwise return the result of evaluating default.
Why does this matter? It means that the code passed to getOrElse doesn't run at all (default is not evaluated) if the Option is defined! For example, this code:
object GetOrElseTest { def main(args : Array[String]) : Unit = { def a() = Some(3) def b() = None val aV = a getOrElse { println("nothing from a :("); 1 } val bV = b getOrElse { println("nothing from b :("); 1 } println("aV=%d, bV=%d".format(aV, bV)) 0 } }
Will print this output (note that the println for getting a, which is defined, never runs):
nothing from b :( aV=3, bV=1
That's awesome and really hard to accomplish in Java. Imagine if log4j could do this; suddenly we wouldn't have any issues with things log.debug("a" + objectThatIsExpensiveToToString.toString()) having a runtime cost even when debug isn't enabled because we wouldn't evaluate the function to create a message at all if debug is off.
The new uniforms are pretty snappy eh first officer!
10 comments:
Thanks, this getOrElse looked complicated in my Play example until I read your post :)
Your example is a bit evil because it involves side effects. True, logging as a side effect is probably the least evil thing you could do and probably acceptable ;) Otherwise, I would prefer only to use the closure to construct a suitable alternative value, where that is not a simple matter or where it might be found in an alternative location.
Great example .. will be handy while using getOrElse method..
Regarding: log.debug("a" + objectThatIsExpensiveToToString.toString()) having a runtime cost even when debug isn't enabled
You can use Logger.isDebugEnabled() to avoid creating Strings that don't get logged because of logger level. However, that applies just to the specific example above. getOrElse can be used for a lot more.
Hello
good article
relating your point on log4j,
in play framework they use call by name (: =>) to avoid immediate evaluation of the toString():
def info(message: => String) {
if (logger.isInfoEnabled) logger.info(message)
}
Francois Scheurer
Your example with logging is bit flawed, since SLF4j already solves this by lazily evaluating the objects only when that debug level is enabled:
LOGGER.debug("This object {}.toString is not always evaluated", expensiveToStringable)
Good explanation!
Very nice example... Good Post!
Great exploration of the getOrElse function! It’s such a powerful feature for handling optional values gracefully. I love how it simplifies code and improves readability by providing a clear fallback for when a value is absent. Your examples illustrate its utility perfectly. It would be interesting to see a comparison with other approaches for handling null or undefined values, just to highlight when getOrElse shines the most. Thanks for shedding light on this magical function—it’s definitely a must-know for any developer!
Digital Marketing Course In Hyderabad
Fantastic article! The explanation of the getOrElse method is insightful and really highlights its practical applications in handling optional values. I appreciate how you provided clear examples to illustrate its usefulness in preventing null pointer exceptions. It would be interesting to see a comparison with other methods for handling defaults in similar scenarios. Thanks for shedding light on this powerful feature!"
Digital Marketing Course In Ameerpet
Post a Comment