부스트코스 서포터즈 3기 활동으로서
코틀린 프로그래밍 기본 1/2(함수편)을 듣고 작성된 포스팅입니다
표준함수 활용(1)
1) 클로저(closure)
클로저란? 람다식으로 표현된 내부 함수에서 외부 범위에 선언된 변수에 접근할 수 있는 개념. 람다식 함수를 이용하다 보면 내부 함수에서 외부 변수를 사용하고 싶을 때가 있다. 이 때 람다식 안에 있는 외부 변수는 값을 유지하기 위해 람다가 포획(capture)한 변수라고 부른다. 실행 시점에서 람다식의 모든 참조가 포함된 닫힌(closed) 객체를 람다 코드와 함께 저장한다. 이때 이러한 데이터 구조를 클로저(closure)라고 부른다다.
기본적으로 함수 안에 정의된 변수는 로컬 변수로 스택에 저장되어 있다가 함수가 끝나면 같이 사라진다. 하지만 클로저 개념에서는 포획한 변수는 참조가 유지되어 종료되어도 사라지지 않고 접근하거나 수정할 수 있게 된다.
fun main() {
val calc = Calc()
var result = 0 // 외부의 변수
calc.addNum(2,3) { x, y -> result = x + y } // 클로저
//result는 람다식 내부에서 재할당 되어 사용
println(result) // 값을 유지하여 5가 출력
//이때 할당된 값은 유지되어 출력문에서 사용가능
//BY 클로저에 의해 독립된 복사본
}
class Calc {
fun addNum(a: Int, b: Int, add: (Int, Int) -> Unit) { // 람다식 add에는 반환값이 없음
add(a, b)
}
//매개변수를 이용하는 경우
fun main() {
filteredNames(2) // 길이가 일치하는 이름만 반환
//출력:[Go]
}
fun filteredNames(length: Int) {
val names = arrayListOf("Kim", "Hong", "Go", "Hwang", "Jeon")
val filterResult = names.filter {
it.length == length // 바깥의 length에 접근
}
println(filterResult)
}
2) let()
// 표준 함수의 정의
public inline fun <T, R> T.let(block: (T) -> R): R { ... return block(this) }
let()은 함수를 호출하는 객체 T를 이어지는 block의 인자로 넘기고 block의 결과값 R을 반환
+여기서 잠깐! T와 R이란?
let()함수를 사용하기 위해 어떤 자료형이더라도 사용할 수 있도록 일반화한 문자, 형식 매개변수
null 가능성 있는 객체에서 let() 활용 : null 검사나 else문이 포함된 문장 대체
fun main(){
val score:Int?=32
//일반적인 null 검사
fun checkScore(a:Int?){
if (a!=null) println("$a")
}
//let을 사용해 null 검사 제거
fun checkScoreLET(a:Int?){
a?.let{ println("$a") }
//?.(엘비스 연산자)를 사용
//ㄴ>null이 아니라면 let이 실행될테니 검사가 필요X
}
checkScore(score)
checkScoreLET(score)
}
체이닝을 사용할 때 let() 활용 : 여러 메서드 혹은 함수를 연속적으로 호출, 마지막 식 반환
fun main() {
var theN: Int = 5
theN=theN.let { it + 3 }.let { println("$it"); it + 8 } //출력:8, 반환:16
//let을 여러 개 사용할 경우 마지막 식이 반환된다
println("$theN")//출력:16
}
3) also() - 받은 객체 그대로 반환
// 표준 함수의 정의
public inline fun <T> T.also(block: (T) -> Unit): T { block(this); return this }
also()는 함수를 호출하는 객체 T를 이어지는 block에 전달하고 객체 T 자체를 반환
fun main() {
var theN: Int = 5
theN=theN.also { println("$it"); it + 8 } //출력:5 반환:5
//also는 계산 결과에 상관없이 원래 받았던 객체(theN)를 반환
println("$theN") //출력:5
}
3) let()과 also() 비교해보기
fun main() {
data class Person(var name:String, var age:Int)
var profile=Person("Soobin",29)
//let을 사용할 경우
val a=profile.let{
it.age=45
"DONE" //마지막 식 반환
}
println(profile) //Person(name=Soobin, age=45)
println("a: $a") //a: DONE
//let은 마지막 식이 반환되므로 "DONE"이라는 string 형태의 값이 반환
//also을 사용할 경우
val b=profile.also{
it.age=22
"DONE" //그러므로 이 문장은 사용되지 않음
//also는 받은 객체 profile을 그대로 반환
}
println(profile) //Person(name=Soobin, age=22)
println("b: $b") //b: Person(name=Soobin, age=22)
//식은 실행되어서 age는 변하였지만 b는 받았던 profile 객체를 그대로 반환
}
코틀린 프로그래밍 기본1/2(함수편)
부스트코스 무료 강의
www.boostcourse.org
'프로그래밍 공부흔적 > Kotlin' 카테고리의 다른 글
[부스트코스][Kotlin]표준함수 활용(3) - 람다식 검사, 시간측정, 난수생성 함수 (0) | 2021.01.29 |
---|---|
[부스트코스][Kotlin]표준함수 활용(2) - apply(), run(),with(), use() (0) | 2021.01.29 |
[부스트코스][Kotlin]프로그램 흐름의 제어 (0) | 2021.01.28 |
[부스트코스][Kotlin]코틀린의 다양한 함수들 (0) | 2021.01.28 |
[부스트코스][Kotlin]람다식과 고차함수의 이해 (0) | 2021.01.28 |
댓글