Reputation: 24588
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?
Upvotes: 1
Views: 170
Reputation: 37633
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
Upvotes: 2
Reputation: 3365
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.
Upvotes: 4
Reputation: 7320
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).
Upvotes: 2