Function Parameters vs Call-by-Name parameters

Is there any practical difference between the following two?
Are there any performance implications of calling one versus the other or is call-by-value just sugar for a function param?
Obviously one could pass a val more easily to the call by name example.
Other than that, I see no practical difference.

  def someFunc(n: => Int): Int = ???

  someFunc(getIntFromDb)
  someFunc(someVal)
  def someFunc(n: () => Int): Int = ???

  someFunc(getIntFromDb)
  someFunc(() => {
    someVal
  })

Other than offering more convenient use-site syntax there is no significant difference.
Convenient use-site syntax is important enough to introduce cbn parameters.

I would not be surprised if, internally, they are more or less treated in the same way.
But, then again, those who know more about the internal details of Scala can correct me.

2 Likes

below is an example

scala> def `while`(condition: => Boolean)(block: => Unit): Unit = if(condition) { block ; `while`(condition) { block } } else { }
while: (condition: => Boolean)(block: => Unit)Unit

scala> var x = 10
x: Int = 10

scala> `while`(x > 0) { println(s"$x") ; x = x - 1 }
10
9
8
7
6
5
4
3
2
1

scala> x
res1: Int = 0

scala> 

using a function parameter the use-site code would not look half as nice

3 Likes

I want to thank LucDupAtGitHub for writing that. While the example of the while loop might seem a bit contrived, I think it does a good job of showing how valuable pass-by-name syntax is for DSLs. Having pass-by-name, combined with the ability to use curly braces for an argument list with one memory and have it contain a block of code really makes DSLs look more like language features. I feel that there are a lot of libraries that benefit from this syntax.

1 Like

You are correct; in fact, they are exactly the same (Function0) once compiled.

1 Like

A less contrived example might be scala.concurrent.Future. Currently, it defines the following apply() method with a by-name parameter:

object Future {
  def apply[T](body: => T)(implicit executor: ExecutionContext): Future[T] = ???
}

This allows you to write

Future {
  // Do some stuff here
  "result"
}

If body was a Function0 instead, it would look much uglier.

Future(() => {
  // Do some stuff here
  "result"
})
2 Likes