티스토리 뷰
아이템2의 주제: 변수의 스코프를 최소화 하는것이 좋다
스코프란?
- 어떤 요소의 스코프라고 한다면 그 요소를 볼 수 있는 컴퓨터 프로그램 영역이다.
- 변수의 스코프라고 한다면 그 변수를 인식하고 사용할 수 있는 범위를 의미한다.
- 코틀린에서는 기본적으로 {} 중괄호로 스코프를 만든다.
상태를 정의할때는 변수와 프로퍼티의 스코프를 최소화 하는 것이 좋다.
- 프로퍼티 보단 지역변수를 사용하는것이 좋다.
- 최대한 좁은 스코프를 갖도록 변수를 사용한다.
스코프 범위 좁히기의 예시
// 가장 안좋은 방법
var user: User
for(i in users.indices) {
user= users[i]
print("user at $i is $user")
}
// 조금 더 좋은 방법
for(i in users.indices) {
val user = users[i]
print("user at $i is $user")
}
// 가장 좋은 방법
for((i, user) in users.withIndex()) {
print("user at $i is $user")
}
변수는 정의할때 초기화하는것이 좋다
- if, when, try-catch, Elvis 표현식을 활용하면 변수를 정의할때 초기화하는것이 편해진다.
// if
val user: User = if(hasValue) {
getValue()
} else {
User()
}
// when
val dayType = when (val dayOfWeek = "Monday") {
"Monday", "Tuesday", "Wednesday", "Thursday", "Friday" -> "Weekday"
"Saturday", "Sunday" -> "Weekend"
else -> "Invalid day"
}
println(dayType) // 출력: Weekday
// try-catch
val result: Int = try {
// 예외가 발생할 수 있는 코드
val numerator = 10
val denominator = 2
numerator / denominator
} catch (e: ArithmeticException) {
// 예외가 발생한 경우 처리할 코드
println("ArithmeticException caught: ${e.message}")
0 // 예외가 발생했을 때 반환할 값
}
println(result) // 출력: 5
// Elvis
val input: String? = null
val result: String = input ?: "Default Value"
println(result) // 출력: Default Value
- 여러 프로퍼티를 한번에 설정할때는 구조분해선언을 활용하는것이 좋다
fun updateWeather(degrees: Int) {
val (description, color) = when {
degrees < 5 -> "cold" to Color.BLUE
degrees < 23 -> "mild" to Color.YELLOW
else -> "hot" to Color.RED
}
}
캡처링
캡처링이 뭘까요?
캡처링(=람다 캡처링): 람다 블럭 외부에서 정의된 변수를 참조하는것
람다식: 다른 함수에 매개변수로 넘길수있는 함수, 중괄호로 묶인다
fun printMessageWithPrefix(messages: Collection<String>, prefix: String) {
var clientErrors = 0
var serverErrors = 0
messages.forEach {
if(it.startsWith("4")) {
clientErrors++ //lamda capture
}else if(it.startsWith("5") {
serverErrors++ //lamda capture
}
}
println("$clientErrors client errors, $serverErrors server errors")
}
하지만 이런 캡처링때문에 문제가 생길 수 있다
아래는 소수를 구하는 코틀린 코드이다
fun runWithSequenceBuilder() {
val primes: Sequence<Int> = sequence {
var numbers = generateSequence(2) { it + 1 }
while (true) {
val prime = numbers.first()
yield(prime) // sequence에 prime을 넘겨준다.
numbers = numbers.drop(1)
.filter { it % prime != 0 }// prime의 배수를 필터링
}
}
println(primes.take(25).toList()) // sequence에 쌓인것중 25개를 List로 변환한다.
}
//[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97]
이렇게 코드를 작성하면 정상 작동한다
하지만 prime 변수를 while 밖으로 빼면 어떻게 될까
fun runWithSequenceBuilderButWrongScope() {
val primes: Sequence<Int> = 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 }
}
}
println(primes.take(25).toList())
}
//[2, 3, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27]
prime 의 선언을 var로 하고 while문 밖에 선언했다
그러면 var 이니깐 while돌면서 prime값이 바뀌면서~ 잘 돌아가겠징? 하지만 아님
시퀀스는 게으른 연산(lazy evaluation)을 사용한다. 위 코드에서 primes 는 시퀀스로 만들어져 있다
filter, drop과 같은 중간 연산에서는 바로 연산을 수행하지 않고 종단 연산인 first를 만날때까지 연산을 누적해서 기다린다.
그래서
1번 순환
prime = 2
filter 대기
drop 대기
2번순환
filter 대기
- 참고한 사이트
https://velog.io/@kartmon61/Effective-Kotlin-%EC%BA%A1%EC%B3%90%EB%A7%81capturing%EC%9D%B4%EB%9E%80
Effective Kotlin - 캡쳐링(capturing)이란?
아이템 2: 변수의 스코프를 최소화하라에서 나온 내용람다 또는 익명 함수와 같은 클로저가 외부 스코프에 있는 변수를 포착하고 이를 내부에서 사용할 수 있는 기능을 말한다. 이로 인해 특정
velog.io
[Kotlin] 코틀린은 람다식에서 외부 변수를 어떻게 참조할까? [람다 캡쳐링] [Lambda Capturing]
람다식 내에서 외부 변수를 변경하는 것에 대해 아무런 의문을 느끼지 않다가, 문득 궁금증이 생겼습니다. 함수를 작성하는 시점에는 람다식의 블럭 내부가 실행되지 않다가, 호출되는 시점에
velog.io
https://lovia98.github.io/blog/kotlin-lamda.html
코틀린에서의 람다 문법과 사용법
Write an awesome description for your new site here. You can edit this line in _config.yml. It will appear in your document head meta (for Google search results) and in your feed.xml site description.
lovia98.github.io
https://bottom-to-top.tistory.com/64
아이템 2 - 변수의 스코프를 최소화하라
가시성 제한 상태를 정의할 때는 변수와 프로퍼티의 스코프를 최소화하는 것이 좋다. 프로프티보다 지역 변수를 사용하는 것이 좋다. 최대한 스코프를 좁게 가지도록 변수를 사용하자. 사용되
bottom-to-top.tistory.com
https://iosroid.tistory.com/79
코틀린(Kotlin) Collections : 시퀀스(sequences)
코틀린(kotlin) 의 시퀀스(sequence) 를 살펴보자. 원문 https://kotlinlang.org/docs/reference/sequences.html 을 보며 정리. kotlin standard library 는 collection 과 함께 또다른 container type 인 sequences (Sequence) 를 가지고 있
iosroid.tistory.com
'공부 > Kotlin' 카테고리의 다른 글
이펙티브 코틀린 - 1장 아이템5 예외를 활용해 코드에 제한을 걸어라 (1) | 2024.08.18 |
---|---|
이펙티브 코틀린 1장 아이템4 - inferred 타입으로 리턴하지 말자 (0) | 2024.07.06 |
이펙티브 코틀린 1장 아이템1 - 가변성을 제한하라 (0) | 2024.06.09 |
null 관련 연산자(안전 호출 연산자, 어설션 연산자, 엘비스 연산자) (0) | 2022.10.29 |
코틀린 기본 문법 정리(2022년 2월 2주 공부 내용 백업) (4) | 2022.09.20 |