No, it will not throw an error (unless you implemented CloudWatchClient to do that on purpose when being initialized). When you prefix a val definition with a lazy modifier, the initializing expression on the right-hand side will only be evaluated the first time the val is used.
Here's a nice example that shows the difference. First a normal object:
scala> object SomeObj {
val x = {
println("initializing x")
"done"
}
}
defined object SomeObj
scala> SomeObj
initializing x
val res0: SomeObj.type = SomeObj$@7c3c3d67
scala> SomeObj.x
val res1: String = done
Now an object containing a lazy val:
scala> object SomeLazyObj {
lazy val x = {
println("initializing lazy x")
"done"
}
}
defined object SomeLazyObj
scala> SomeLazyObj
val res2: SomeLazyObj.type = SomeLazyObj$@3e4636c3
scala> SomeLazyObj.x
initializing lazy x
val res3: String = done
You can probably now figure that intuitively what lazy does in your example is to avoid initializing cloudWatchClient on the spot. In fact, its initialization happens exactly before close() is called, since operands are evaluated left-to-right, and the method close() needs cloudWatchClient initialized before it can itself be called.
It is worth noting that unlike a def, a lazy val is never evaluated more than once. After the first evaluation of the lazy val, the result is stored, to be reused when the same val is used subsequently.
However, there is one trick to it: if during the first evaluation of your lazy val you get an Exception, the next time you will try to access the lazy val, it will try to re-evaluate itself.