KoreanFoodie's Study

Scala 1 - Call by value vs. Call by name 본문

Tutorials/Scala

Scala 1 - Call by value vs. Call by name

GoldGiver 2019. 4. 23. 15:37

스칼라에서 call by value와 call by name의 차이를 알아보자


There is two strategy to evaluate values.

Call-by-value

  • Evaluate the arguments first, then apply the function to them

Call-by-name

  • Just apply the function to its arguments, without evaluating them

Let's see the example.

def square (x: Int) = x * x

[cbv] square(1+1) ~ square(2) ~ 2 * 2 ~ 4

[cbn] square(1+1) ~ (1+1) * (1+1) ~ 2 * (1+1) ~ 2 * 2 ~ 4

So what's the difference?

Call-by-value evaluates arguments once, on the other hand, Call-by-name DO NOT evaluate unused arguments.

So if there is an argument could not be used depending on conditions, then Call-by-name could be more efficient.

def f(x : Double, y: Double) = 
    if x 
        0
    else 
        y

In this case, Call-by-value compute both x and y, but Call-by-name may not compute y!


Scala's evaluation strategy

Call-by-value

  • By default

Call-by-name

  • Use "=>"
def loop:Int = loop    // Just a normal, boring loop :)

def one(x: Int, y: => Int) = 1

one(1+2, loop)     // does not compute loop, therefore result is 1

one(loop, 1+2)    // it tries to compute loop, falls into divergence and never ends.

Scala's name binding strategy

Call-by-value

  • Use "val" (also called "field")

  • Evaluate the expressiong first, then bind the name to it

Call-by-name

  • Use "def" (also called "method")

  • Just bind the name to the expression, without evaluating

def a = 1 + 2 + 3
val a = 1 + 2 + 3     // a is now just 6
def b = loop
val b = loop        // it will loop forever, because it tries to compute b. Remember, functions are not meant to be evaluated when it is defined!

def f(a: Int, b: Int): Int = a * b -2

Exercise: square root calculation

  • Calculate square roots with Newton's method
def isGoodEnough(guess: Double, x: Double) =
    ??? // guess*guess is 99.9% close to x

def improve(guess: Double, x: Double) =
    (guess + x/guess) / 2

def sqrtIter(guess: Double, x: Double): Double =
    ??? // repeat improving guess until it is good enough

def sqrt(x: Double) =
    sqrtIter(1, x)

sqrt(2)
  • Answer :
object HelloWorld {

  def main(args: Array[String]): Unit = {

    def isGoodEnough(guess: Double, x: Double) =
      guess * guess / x > 0.999 && guess * guess / x < 1.001
     // guess * guess is 99.9% close to x

    def improve(guess: Double, x: Double): Double =
      (guess + x / guess) / 2

    def sqrtIter(guess: Double, x: Double): Double =
      if (isGoodEnough(guess, x))
        guess
      else
        sqrtIter(improve(guess, x), x)

      // repeat improving guess until it is good enough

    def sqrt(x: Double) =
      sqrtIter(1, x)

    sqrt(2)     // For check, println(sqrt(2))

  }

}

'Tutorials > Scala' 카테고리의 다른 글

Scala 6 - Datatypes  (0) 2019.04.23
Scala 5 - Currying  (0) 2019.04.23
Scala 4 - Closures, revisted  (0) 2019.04.23
Scala 3 - Tail Recursion & Higher-Order Functions 1  (0) 2019.04.23
Scala 2 - Blocks in Scala & Lazy val  (0) 2019.04.23
Comments