Call By Value vs. Call By Name Evaluation

Animesh GuptaAnimesh Gupta
4 min read

Mostly all programming languages follow two primary ways of evaluating function calls.

  • Call by Value / Eager evaluation

  • Call by Name / Lazy Evaluation

Both evaluating strategies reduce to the same final value as long as the following hold true ::

  • The reduced expression consists of pure functions.

  • Both evaluations terminate.

Que. How does the compiler and further the execution environment identifies whether a function or method is call by value or call by name ?

Ans. The compile time syntax identifies call by value or call by name mechanism. The execution environment follows the function definition to decide between call by value and call by name.

Some languages optimize the “call by name” mechanism into “call by need”, i.e., lazy evaluation only by default to avoid repeated computations. e.g. Haskell

Que. When to use Call by Value evaluation strategy ?

Ans. Call by value finds it’s usefulness when we want efficiency and predictability of execution. Also, it has the advantage of evaluating every function argument only once. e.g. enabling a counter, concatenating outputs incrementally, etc.

Que. When to use Call by Name evaluation strategy ?

Ans. Call by name shines when a function argument is either not at all used in the function body or we need to evaluate the argument again and again from scratch. This strategy is best for lazy evaluation, performance optimization and for avoiding unnecessary evaluations. e.g. mapping rows from a SQL query into objects where the task of mapping for each row needs to be from beginning to end, again and again.

Language Specific Design

LanguageDefault StrategySupports Call Name ?
CCall by ValueN/A
C++Call by ValueN/A
JavaCall by ValueSimulated using Supplier<T>
ScalaCall by ValueYes
PythonCall by ValueSimulated using Lambdas
LispCall by ValueYes
JuliaCall by ValueSimulated using Thunks
HaskellCall by NeedYes
GoCall by ValueSimulated using ( func() )
RustCall by ValueSimulated using Closures
JavaScriptCall by ValueSimulated using Higher Order Functions

Call By Value Example with Output using Scala coding language.

Note :: Remember, in Call by Value evaluation strategy, arguments are evaluated before passing to the function.

object SumOfSquaresByValue {
  def sumOfSquares(x: Int, y: Int): Int = {
    x * x + y * y
  }

  def main(args: Array[String]): Unit = {
    val a = 3
    val b = 4
    println(s"Sum of squares of $a and $b: " + sumOfSquares(a, b))
  }
}

Output :: 
Sum of squares of 3 and 4: 25

Call By Name Example with Output using Scala coding language.

Note :: Remember, in Call by Name evaluation strategy, arguments are evaluated each time they are accessed inside the function.

object SumOfSquaresByName {
  def sumOfSquares(x: => Int, y: => Int): Int = {
    println(s"Evaluating x: $x")
    println(s"Evaluating y: $y")
    x * x + y * y
  }

  def main(args: Array[String]): Unit = {
    var a = 3
    var b = 4

    def computeA(): Int = {
      println("Computing a...")
      a
    }

    def computeB(): Int = {
      println("Computing b...")
      b
    }

    println("Calling sumOfSquares...")
    println("Result: " + sumOfSquares(computeA(), computeB()))
  }
}

Output :: 
Calling sumOfSquares...
Computing a...
Evaluating x: 3
Computing b...
Evaluating y: 4
Computing a...
Computing b...
Result: 25
ApproachEvaluation StrategyReusabilityBehaviour
Call by ValueEvaluates before function callSimpleEfficient when value used multiple times
Call by NameEvaluates each time it is accessedUseful for lazy computationsMay cause repeated evaluations
1
Subscribe to my newsletter

Read articles from Animesh Gupta directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Animesh Gupta
Animesh Gupta