KoreanFoodie's Study
Scala 2 - Blocks in Scala & Lazy val 본문
스칼라 튜토리얼, scala에서 lazy val에 대해 알아보자
Blocks and Name Scoping
Blocks in scala
Block is an expression. It also allow nested name binding.
Block allows arbitraty order of "def"s, but not "val"s(think about why).
Scope of names
Block example :
val t = 0
def f(x: Int) = t + g(x)
def g(x: Int) = x * x
val x = f(5)
val r = {
val t = 10
val s = f(5)
t + s
}
val y = t + r
A definition inside a block is only accessible within the block.
A definition inside a block shadows definitions of the same name
outside the block.
A definition inside a block is accessible unless it is shadowed.
A function is evaluated under the environment where it is defined, not the environment where it is invoked(Important!).
Q. In the above code, what would be the result of 's' in 'r' block(at line 7)?
A. 25! Since function 'f' is evalueated as it is defined, because 't' is initialized as 0, therefore 'f' becomes same as 'g'.
Example: def with no arguments
val t = 0
def x = t+t // is treated as def x() = t
val r = {
val t = 10
x } // is treated as x(), r is 0.
Semi-colons and Parenthesis
Block
-
Can write two definitions/expressions in a single line using ;
-
Can write one definition/expression in two lines using (), but can omit () when clear
// ok
val r = {
val t = 10; val s = square(5); t +
s }
// Not ok
val r = {
val t = 10; val s = square(5); t
+ s }
// ok
val r = {
val t = 10; val s = square(5); (t
+ s) }
Exercise: Writing better code using blocks
- Make the following code better
def isGoodEnough(guess: Double, x: Double) =
guess*guess/x > 0.999 && guess*guess/x < 1.001
def improve(guess: Double, x: Double) =
(guess + x/guess) / 2
def sqrtIter(guess: Double, x: Double): Double = {
if (isGoodEnough(guess,x)) guess
else sqrtIter(improve(guess,x),x)
}
def sqrt(x: Double) =
sqrtIter(1, x)
sqrt(2)
- Solution :
def sqrt(x: Double) = {
def isGoodEnough(guess: Double, x: Double) =
guess*guess/x > 0.999 && guess*guess/x < 1.001
def improve(guess: Double, x: Double) =
def sqrtIter(guess: Double, x: Double): Double = {
if (isGoodEnough(guess,x)) guess
else sqrtIter(improve(guess,x),x)
}
sqrtIter(1, x)
}
sqrt(2)
Lazy Call-By-Value
-
Use "lazy val"
-
Evaluate the expression first time it is used, then bind the name to it
def f(c: Boolean, i: =>Int): Int = {
lazy val iv = i
if (c) 0
else iv * iv * iv
}
f(true, {println("ok"); 100+100+100+100})
f(false, {println("ok"); 100+100+100+100})
Q. What would output look like?
A. In console window, just single "ok".
If we remove 'lazy' from 'lazy val iv = i', then there will be 1 "ok"s(Since it is evaluated when it is initialized).
And if we replace 'lazy val' with 'def', there will be 3 "ok"s(only from second funtion call. It computes 'iv' during multiplicatoin every single time).
'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 1 - Call by value vs. Call by name (0) | 2019.04.23 |