isPrime 함수를 sumOfPrimes 밖에서 정의할 수는 없다. 왜냐하면 isPrime이 seq 값을 가두어 닫기(close over) 때문이다. 이런 구조를 클로저(closure)라고 한다. 다음 장에서 배우겠지만 클로저는 자신이 가두어 닫은 변수를 함수 인자로 받는 것과 비슷하다. 앞의 코드를 다시 쓰면 다음과 같다.
fun sumOfPrimes(limit: Int): Long { val seq: Sequence<Long> = sequenceOf(2L) + generateSequence(3L, { it + 2 }).takeWhile{ it < limit } return seq.filter { x -> isPrime(x,seq) }.sum() } fun isPrime(n: Long, seq: Sequence<Long>): Boolean = seq.takeWhile { it * it <= n }.all { n % it != 0L }
클로저를 사용하면 isPrime 함수를 호출하려고 람다를 정의하는 대신 함수 참조(자바의 메서드 참조와 같음)를 사용할 수 있다. 한편, 클로저를 사용하면 isPrime 함수를 sumOfPrimes 함수 밖에서 사용할 수 없게 된다. 여러분이 이런 특성을 원할 수도 있고 원하지 않을 수도 있다.
여기서 (n: Long, seq: Sequence<Long>)을 파라미터로 받는 isPrime 함수를 sumOfPrimes 밖에서 다른 용도로 사용할 가능성이 별로 없다. 그런 경우에는 isPrime을 sumOfPrimes의 로컬 함수로 만들어서 클로저와 함수 참조를 사용하게 만드는 편이 더 낫다.