0

I have seen quite a few topics dealing with the difference between val, lazy val and def but none of them seemed to answer exactly to my question.

I'm wondering what is the difference between a val (or lazy val) and a def when the val is a function. Indeed, most answers I read explained that a val is evaluated only once whereas a def is evaluated each time it is called. What I don't get is when a val is used as in the following code :

lazy val name : Int => Int = {
  case n if(n < 20) => //terminal case... 
  case n if(n < 100) => //terminal case...
  case n if(n < 1000) => name(n / 100) + //something unrelevant...
}
val result = (1 to 1000).map(name).sum

To evaluate result, it seems to me that name is going to be "evaluated" for each element of the sequence 1 to 1000. How is it different from using a def in that particular case ?

Dici
  • 25,226
  • 7
  • 41
  • 82
  • 2
    My understanding is that the `lazy` modifier delays the value evaluation as long as it can, that means that until the first iteration of `map`, `name` is not defined, after the first iteration `name` has a definition that is reused in the successive iterations, meanwhile using `def` would mean to create a function every time. – Ende Neu Aug 13 '14 at 15:11
  • So using def would be equivalent to create a function object for each call and then apply it to the arugments ? – Dici Aug 13 '14 at 15:13
  • 2
    That is my understanding, [this answer](http://stackoverflow.com/questions/18887264/what-is-the-difference-between-def-and-val-to-define-a-function) illustrates the differences, the only thing you have changed is that the val evaluation is delayed until it is really needed, but other than that val will contain always the same function, while def will contain always a different function. – Ende Neu Aug 13 '14 at 15:15
  • Thanks, I had missed that one. – Dici Aug 13 '14 at 15:21

1 Answers1

2

To evaluate result, it seems to me that name is going to be "evaluated" for each element of the sequence 1 to 1000.

This is not true. lazy val means that before you invoke it the first time, name is not evaluated. After the first call, it will evaluate its definition and be fully defined, then other calls use the already defined function.

You could definitely define your function name with def and it would be the same.

Basically val and def would be identical, using lazy val just defer the full evaluation of your function until the first call.

vptheron
  • 7,426
  • 25
  • 34
  • 1
    Are you sure ? According to the tbest answer of the question linked by **Ende Neu**, each call of a method defined by def creates a new Function object, which would apparently not be the case for a val. – Dici Aug 13 '14 at 15:23
  • In the code in the linked question yes it does create a new function since it *defines* a function `even` that has a function for *returned value*, it is not f(Int) -> Boolean, but f() -> (Int -> Boolean). If you define `def even(i: Int): Boolean` it creates only one function - and is equivalent to `val even: Int => Boolean = ...`. Hope it makes more sense. – vptheron Aug 13 '14 at 22:09