One of the benefits of call-by-name is that expensiveOperation() will not get run in the following examples:
Call-by-value:
def test( x: Int, y: Int ): Int = x * x
// expensiveOperation is evaluated and the result passed to test()
test( 4, expensiveOperation() )
Call-by-name:
def test( x: Int, y: => Int ): Int = x * x
// expensionOperation is not evaluated
test( 4, expensiveOperation() )
My question though is why would you declare a function parameter (y in my case) when you aren't going to use it?
Your example is a bit contrived, consider this code
def test( x: Boolean, y: => Int ): Int = if(x) y else 0
// expensionOperation is not evaluated
test( false, expensiveOperation() )
When the first parameter is false you are saving a lot of time not evaluating expensive operation.
It is just a contrived example to illustrate the idea of call-by-name, namely that the argument passed in is never evaluated if never called.
Perhaps a better example would be the following:
trait Option[+T] {
def getOrElse[B >: A](default: => B): B
}
If the Option
is Some
, then the wrapped value is returned and default
is never evaluated. If it is None
and only when it is None
will default
be evaluated (and consequently returned).
Using logging is a much better example:
def debug(msg: String) = if (logging.enabled) println(msg)
debug(slowStatistics()) // slowStatistics will always be evaluated
While in the case of call-by-name:
def debug(msg: => String) = if (logging.enabled) println(msg)
debug(slowStatistics()) // slowStatistics will be evaluated only if logging.enabled
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.