Kotlin의 lambda expression
위 페이지를 참고하여 kotlin의 특징적인 문법인 lambda expression에 대해 알아보자
개요
이번에 확인할 lambda expression의 내용 중 제일 핵심은
"함수도 하나의 자료형이고 리터럴로서 의미를 가진다"는 것이다
함수를 담은 변수
함수도 하나의 값이나 다름 없기 떄문에 변수에 함수를 저장할 수 있다
lambda expression은 함수도 하나의 값이라는 개념에서 시작한다
fun main() {
val fun1Var = ::fun1
fun1Var()
fun2()
}
fun fun1(){
println("this is fun1")
}
val fun2 = {
println("this is fun2")
}
이런 식으로 말이다
::는 함수참조연산자라고 부른다
c로 생각해봤을 때 fun1자체는 주소값이고
그걸 타고 들어가는 -> 연산자라고 생각하면 되겠다
이때 fun1Var의 자료형은 () -> Unit이다
그러니까 자료형이 함수라는 뜻이다
lambda expression
위의 코드에서 특이한 점은 중괄호로 감싸진 '함수'를 하나의 값으로 취급해 변수에 대입한 것이다
이때 이 '함수'를 lambda expression이라고 하고
다른 언어에서의 익명함수와 유사하다
lambda expression의 구성은 다음과 같다
val sum: (Int, Int) -> Int = { x: Int, y: Int -> x + y }
타입이 있는 앞부분과 실제 함수의 내용인 중괄호 부분이 있는데
이때 매개변수가 없으면 앞부분을 생략해서 우리가 위에서 본 중괄호만 남은 형태가 된다
중괄호 내부의 매개변수의 타입과 매개변수의 이름 마저도 생략할 수 있는데
더 알아보면서 예시를 확인해보자
함수를 리턴하는 함수
함수 또한 함수를 리턴값으로 가질 수 있다
다음 코드를 보자
fun main() {
val yes = saySomething(true)
val no = saySomething(false)
yes()
no()
}
fun saySomething(isYes: Boolean) : () -> Unit {
if(isYes){
return sayYes
} else {
return sayNo
}
}
val sayYes: () -> Unit = {
println("Yes")
}
val sayNo: () -> Unit = {
println("No")
}
saySomething이라는 함수는 () -> Unit 형태의 자료형을 리턴한다
그러니까 saySomething이라는 함수는 함수를 리턴한다는 뜻이
함수인 매개변수
이번엔 심지어 매개변수 마저도 함수일 수도 있다
참고로 당연하지만 자료형이 함수인 변수도 nullable 하다 null일 수 있다는 뜻이다
만약 nullable한 함수를 받았고 이를 안전하게 호출하려면 함수명?.invoke()를 쓰자
아래 예시를 보자
fun main() {
buySomething(checkWallet, 400)
buySomething(null, 400)
}
fun buySomething(checkWallet: ((Int) -> Int)?, price: Int) {
if(checkWallet != null){
val money = checkWallet(4)
if(money >= price)
println("you can buy something")
else
println("you can't buy something")
} else {
println ("you forgot wallet")
}
}
val checkWallet: (Int) -> Int = { coin ->
coin*100
}
<출력결과>
you can buy something
you forgot wallet
checkWallet은 동전의 개수를 받아서 100만큼 곱해 리턴해주는 (Int) -> Int 타입의 함수이다
이 checkWallet이 바로 함수인 매개변수이다
buySomething은 checkWallet을 받아서 물건가격과 비교한다음 구매할 수 있는지 없는지를 출력한다
이때 checkWallet이 null 값이면 지갑을 안가져왔다는 문장을 출력한다
매개변수를 생략하면 it으로 명시할 수 있다
fun main() {
buySomething(checkWallet, 400)
buySomething(null, 400)
}
fun buySomething(checkWallet: ((Int) -> Int)?, price: Int) {
if(checkWallet != null){
val money = checkWallet(4)
if(money >= price)
println("you can buy something")
else
println("you can't buy something")
} else {
println ("you forgot wallet")
}
}
val checkWallet: (Int) -> Int = {
it*100
}
매개변수에 함수리터럴(=lambda expression)을 직접넣을 수도 있고
후행람다문법이라고 함수인 매개변수가 가장 마지막 매개변수라면 함수 호출 뒷부분에 람다표현식을 붙여놓을 수 있다
그동안 사용했던 Column같은 Composable에게 별다른 매개변수가 없을 때 그냥 중괄호만 있어도 됐던 이유다
BirthDayCard App - Column Container, 람다후행문법
fun main() {
showMessage(returnMessage)
showMessage({"this is message"})
showMessage(){"this is message"}
}
fun showMessage(m: ()->String) {
println(m())
}
val returnMessage: () -> String = {
"this is message"
}
<출력결과>
this is message
this is message
this is message
repeat 함수
함수를 위한 for문인 repeat 함수가 있다(물론 아직 kotlin의 for문은 안 배웠지만..)
repeat함수의 상세는 아래와 같다
repeat(times: Int, action: (Int) -> Unit)
맨 마지막 매개변수가 함수이기 때문에 후행람다문법을 이용해서 이쁘게 쓸 수 있다
근데 action의 자료형 중에서 매개변수 부분이 Int인데 왜 그냥 암거나 다 넣을 수 있는 거지? 저 Int가 times인가?
암튼 repeat는 다음과 같이 이용할 수 있다
fun main() {
repeat(5){
sayHello()
}
}
val sayHello: () -> Unit = {
println("say hello")
}
<출력결과>
say hello
say hello
say hello
say hello
say hello
'기타 > 안드로이드' 카테고리의 다른 글
Android Studio Debugger (0) | 2022.10.14 |
---|---|
Dice Roller App - remember API (0) | 2022.10.14 |
Kotlin의 class, property delegation (0) | 2022.10.14 |
Kotlin의 null (0) | 2022.10.14 |
Kotlin의 조건문 (0) | 2022.10.14 |