3

It could sound like a rookie mistake but I do a lot of that. While passing lazy evaluated block or value into a function, if I forget somehow make that function's corresponding parameter lazy (pass/call by name) its causing some confusions at first glance because it forces evaluation.Very small ex;

lazy val a = {println("a");1}
def myfunc(b:Int){println("hello")}
myfunc(a);

Output:

a
Hello

So my question, is there any compiler help for this problem?(flag etc.) Or this is a kind of thing that I should take care of ?

altayseyhan
  • 735
  • 1
  • 7
  • 18
  • What would be a sign the compiler can watch out for to detect that you meant `=>Int` but wrote `Int`? – Jasper-M Dec 29 '17 at 12:40
  • parameter which is passed to that function, marked as lazy or not – altayseyhan Dec 29 '17 at 12:51
  • 1
    Passing a lazy variable by value to a function is no different then using in some other way. At some point evaluation needs to happen. How can compiler decide whether the place, where it is happening is in fact the place where you meant it to happen - that's the question. – Dima Dec 29 '17 at 14:53

1 Answers1

5

You can move the problem into type system.

  1. Don't use lazy vals explicitly, instead...
  2. Define a box for lazily evaluated values:

class Lazy[A](body: => A) {
  lazy val value = body
}

object Lazy {
  def apply[A](body: => A) = new Lazy[A](body)
}

Now you will have a little bit of help from the compiler:

val a = Lazy {
  println("a")
  1
}

def myfunc(b: Lazy[Int]) = {
  println("hello")
}

myfunc(a) // ok, and it doesn't print "a" since it never uses it
// myfunc(42) // won't compile

def myfunc2(b: Int) = b + 42

// myfunc2(a) // does not compile
myfunc2(a.value) // ok, explicitly evaluate - or consider refactoring myfunc2
Oleg Pyzhcov
  • 7,323
  • 1
  • 18
  • 30