Rodrigo Rodrigo - 2 months ago 11
Scala Question

Call-by-value and by-name equivalence

I'm working in a Coursera course on functional programming and at some point they discuss the difference between call-by-value and call-by-name evaluation techniques. They're some point that confuses me, they say:


Both techniques reduce to the same final values as long as:


  1. the reduced expressions consists of pure functions and

  2. both evaluations terminate




which seems to be a lambda calculus theorem.

Could you explain me what they mean by "the reduced expressions conssist of pure functions"?

Answer

A pure function is one which has no side-effects (such as doing IO or changing any value not local to the function). An example of a pure function would be:

def inc(x: Int) = x+1

An example of an impure function would be:

var sum = 1
def addToSum(x: Int) = {
    sum += x
    sum
}

So now let's consider these two methods, which only differ by whether they take their arguments by name or value:

def doubleByValue(x: Int) = x + x
def doubleByName(x: =>Int) = x + x

Now if we use both of these with the pure function, the result is the same:

doubleByValue(inc(2)) // => 6
doubleByName(inc(2)) // => 6

But if we apply them to the impure function, the result differs:

sum = 1 // Let's reset sum, so the result isn't affected by previous uses
doubleByValue(addToSum(2)) // => 6, the value of `sum` is now 3
sum = 1 // Let's reset sum, so the result isn't affected by previous uses
doubleByName(addToSum(2)) // => 8, the value of `sum` is now 5

The difference is that the ByName version calls the function twice and adds the two results, whereas the ByValue version calls it once, saves the result and adds it to itself.

For the pure function this makes absolutely no difference - given the same argument, it will always return the same result, so it makes no difference whether you call it once and use the saved result twice or you call it twice (except for performance).

For the impure function it makes a big difference as the value of the sum variable is changed each time the function is called.