() => A 는 매개변수를 받지 않고 A를 돌려주는 함수이다. 이런 형태를 Thunk라라 한다. 함수형 언어에서 Thunk는 immutable을 지원하는 pure한 비동기 함수이다. ( () => A 또는 => A 라는 형태를 가진다)
scala와 spark의 내부 코드에 종종 보이는 코드이다.
아래 예시를 보면, ifThunk 함수는 첫 번째 매개변수를 Boolean 타입으로 받고
onTrue와 onFalse라는 Thunk 함수를 받는다.
이럴 때는 호출하는 부분에서 () =>{ }의 형태로 사용해야 한다
def ifThunk[A] (cond:Boolean, onTrue:() => A, onFalse:() => A): A = {
if (cond) onTrue() else onFalse()
}
val a = 1
ifThunk(a > 0, () => {println("true")}, () => {println("false")})
결과는 true이다.
() => A 표현식을 =>A로 바꿔도 동일한 기능을 사용할 수 있다. 대신 호출하는 부분에서 () =>을 사용하지 않는다.
def ifThunk2[A] (cond:Boolean, onTrue: => A, onFalse: => A): A = {
if (cond) onTrue else onFalse
}
val b = 1
ifThunk2(b > 0, {println("true")}, {println("false")})
// not print
ifThunk2(b > 0, () => {println("true")}, () => {println("false")})
결과를 보면, true 하나만 출력한다.
(참고로 아래 코드도 잘 동작한다)
ifThunk2(b > 0, println("true"), println("false"))
() => {}를 사용한 라인에서는 출력이 없다....
println으로 확인해 보면, <function0>을 리턴한 코드가 된 것이다.
println(ifThunk2(b > 0, () => {println("true")}, () => {println("false")}))
() => A 대신 => A를 사용하면, 표현식을 알아서 처리한다. 아래는 에러가 발생하지 않는다.
ifThunk2(b > 0, println("true"), 3)
결과는 true가 출력된다.
만약, 3이라는 표현식에 결과가 나타나도록 하려면 다음과 같다.
println(ifThunk2(b < 0, {println("true")}, 3))
결과는 3이 출력된다. ifThunk2는 3을 리턴하였다. 유연성 짱이다.
그리고, 매개변수를 함수로 넘길 때 다른 이슈를 설명한다.
multiply는 간단히 Thunk를 이용해 곱하는 함수이다.
def multiply(b:Boolean, i: => Int) = if(b) i * i else 0
println(multiply(true, 2))
결과 값은 4이다.
실제 호출 순을 살펴본다.
println(multiply(true, {println("a") ; 2}))
결과는 다음과 같다. 매개변수에 사용하는 함수는 호출될 때마다 발생한다. 2번 호출했으니 2번 출력된다.
a
a
4
이를 한번에 모았다가 한번에 함수를 호출하려면, lazy val를 사용한다.
def multiply2(b:Boolean, i: => Int) = { lazy val j = i; if(b) j + j else 0 }
println(multiply2(true, 2))
println(multiply2(true, {println("b") ; 2}))
결과는 다음과 같다. 즉 넘긴 함수는 코드 안에서 여러 번 호출되더라도 한번만 호출된다. 이를 memoization이라 한다.
(lazy j에서 확인할 수 있다)
b
4
lazy val과 thunk가 lazy evaluation 의 핵심 개념이다.
'scala' 카테고리의 다른 글
[scala] List concatenation 리스트 결합 예시 (0) | 2017.01.11 |
---|---|
[scala] zip/unzip 예시 (0) | 2017.01.10 |
[scala] 이항 함수를 사용하는 함수와 for 내장 함수 비교 (0) | 2017.01.04 |
[scala] reflection api 예시 (0) | 2016.12.21 |
[scala] 스칼라 스크립트 실행 코드 예시 (0) | 2016.12.16 |