// 나쁜 예// user가 for loop 외부에 존재var user: Userfor (i in users.indices) { user = users[i]print(user)}// 좋은 예// user가 for loop 내부에 존재for (i in users.indices) {val user = users[i]print(user)}// 더 좋은 예// user가 for loop 내부에 존재for ((i, user) in users.withIndex()) {print(user)}
스코프가 좁을수록 프로그램을 추적하고 관리하기 쉽다.
여러 프로퍼티를 한번에 설정해야 하는 경우 **구조분해 선언(destructuring declaration)**을 활용한다.
// 나쁜 예funupdateWeather(degrees: Int) {val description: Stringval color: Intif (degrees <5) { description ="cold" color = Color.BLUE } elseif (degrees <23) { description ="mild" color = Color.YELLOW } else { description ="hot" color = Color.RED }}// 좋은 예funupdateWeather(degrees: Int) {val (description, color) =when { // 구조분해 선언 degrees <5->"cold" to Color.BLUE degrees <23->"mild" to Color.YELLOWelse->"hot" to Color.RED }}
캡처링
시퀀스를 활용해 에라토스테네스의 체(소수를 구하는 알고리즘)를 구하면 다음과 같다.
val primes =sequence {var numbers =generateSequence(2) { it +1 }while (true) {val prime = numbers.first()yield(prime) numbers = numbers.drop(1).filter { it % prime !=0 } }}print(primes.take(10).toList()) // [2, 3, 5, 7, 11, 13, 17, 19, 23, 29]
prime을 반복문 외부에 선언하면 결과가 이상하게 나온다.
val primes =sequence {var numbers =generateSequence(2) { it +1 }var prime: Int// 외부에 선언while (true) { prime = numbers.first()yield(prime) numbers = numbers.drop(1).filter { it % prime !=0 } }}print(primes.take(10).toList()) // [2, 3, 5, 6, 7, 8, 9, 10, 11, 12]
시퀀스를 활용하기 때문에 filter의 연산이 지연(lazy evaluation)된다. 따라서 최종적인 prime 값으로만 filter가 평가되기 때문에 prime이 2일때 필터링된 4를 제외하고 drop만 동작한 결과를 반환한다.