() => 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 의 핵심 개념이다. 





*참조 : https://github.com/fpinscala/fpinscala

Posted by 김용환 '김용환'

댓글을 달아 주세요