Kotlin

[android : kotlin] 코틀린 람다식(Lambda Expression) 사용 방법

람다식(Lambda Expression)이란? 이름이 없어도 함수 역할을 하는 익명 함수의 하나의 형태이다. 람다식은 화살표 표기법을 사용한다. 람다식은 고차 함수에서 인자로 넘기거나 결과값으로 반환 등을 할 수 있다.

 

 

 

 

 

■람다식의 예

//이름이 없는 함수 형태이다.
{ x , y -> x + y }  

val multi = {x: Int, y:Int -> x * y}

println(multi(10,20)

val multi2: (Int, Int) -> Int = {x: Int, y:Int ->
	println("x*y")
    x*y // 마지막 표현식이 반횐됨.    
}

 

■람다식의 구성


<출처 : 유튜브 – 아카룸 프로그래밍>

 

■자료형의 생략

//생략되지 않은 전체 표현
val multi: (Int, Int) -> Int = {x:Int, y:Imt -> x * y}  

// 선언 자료형 생략
val mulit = {x:Int, y:Int -> x * y} 

//람다식 매개변수 자료형의 생략
val multi: (Int, Int) -> Int = {x, y -> x * y}  

//에러!! 추론 불가
val multi: {X,y -> x *y}  

 

■람다식 안에 람다식이 있는 경우

val nestedLambda: ()->()->Unit = { { println("nested") } }

 

■반환값이 없거나 매개변수가 하나만 있을 경우

val greet: ()->Unit 
val square: (Int)->Int = { x -> x * X }

 

fun main() {
    var result: Int
        // 람다식을 매개변수와 인자로 사용한 함수
        result = highOrder({ x, y -> x + y}, 10, 20)
        println(result)

        result = highOrder({ x, y -> x * y}, 10, 20)
        println(result)

        result = highOrder({ x, y -> x - y}, 10, 20)
        println(result)    
        
        // 반환값이 없는 람다식의 선언
        val out: () -> Unit = { println("Hello World!") }
        // 추론이 가능하므로 val out = { println("Hello World!") }와 같이 생략 가능
        // 람다식이 들어있는 변수를 다른 변수에 할당
        out() // 함수처럼 사용가능    

}

fun highOrder(caluate: (Int, Int) -> Int, a: Int, b: Int): Int {
    return caluate(a, b)
}
 

[출력결과]

30
200
-10
Hello World!

 

■값에 의한 호출(CallByValue) : 함수가 인자로 전달될 경우 – 람다식 함수는 값으로 처리되어, 그 즉시 함수가 수행된 후 값을 전달

fun main() {
	val result = callByValue(lambda()) // 람다식 함수를 호출
	println(result)
}

fun callByValue(b: Boolean): Boolean { // 일반 변수 자료형으로 선언된 매개변수
	println("callByValue function")
	return b
}

val lambda: () -> Boolean = { // 람다 표현식이 두 줄이다
	println("lambda function")
	true // 마지막 표현식 문장의 결과가 반환
}

[출력결과]

lambda function
callByValue function
true

 

■이름에 의한 호출(CallByName)

fun main() {              
	val result2 = callByName(otherLambda) // 람다식 이름으로 호출
	println(result2)

}

fun callByName(b: () -> Boolean): Boolean { // 람다식 함수 자료형으로 선언된 매개변수
	println("callByName function")
	return b()
}

val otherLambda: () -> Boolean = {
	println("otherLambda function")
	true
}

[출력결과]

callByName function
otherLambda function
true

 

■다른 함수의 참조에 의한 호출

fun main() {
	// 1. 인자와 반환값이 있는 함수
	val res1 = funcParam(3, 2, sum)
	println(res1)

	// 2. 인자가 없는 함수
	hello(::text) // 반환값이 없음
	
    // 3. 일반 변수에 값처럼 할당
	val likeLambda = ::sum
	println(likeLambda(6,6))
}

fun sum(a: Int, b: Int) = a + b

fun text(a: String, b: String) = "Hi! $a $b"

fun funcParam(a: Int, b: Int, c: (Int, Int) -> Int): Int {
	return c(a, b)
}

fun hello(body: (String, String) -> String): Unit {
	println(body("Hello", "World"))
}

[출력결과] sum은 람다식이 아님으로 오류가 발생된다. sum을 람다식 처럼 호출하기 위해 콜론(::)를 사용하여 참조방식으로 호출한다.

No value passed for parameter 'a'
No value passed for parameter 'b'
Function invocation 'sum(...)' expected
Type mismatch: inferred type is Int but (Int, Int) -> Int was expected

[출력 결과] ::sum으로 호출한 경우

5
Hi! Hello World
12

 

■매개변수가 없는 경우

fun main() {
// 매개변수 없는 람다식 함수
	noParam({ "Hello World!" })
	noParam { "Hello World!!!!" } // 위와 동일 결과, 소괄호 생략 가능
}
// 매개변수가 없는 람다식 함수가 noParam 함수의 매개변수 out으로 지정됨
fun noParam(out: () -> String) = println(out())

[출력결과]

Hello World!
Hello World!!!!

 

■매개변수가 1개 있는 경우

fun main() {

	// 매개변수가 하나 있는 람다식 함수
	oneParam({ a -> "Hello World! $a" })
	oneParam { a -> "Hello World!! $a" } // 위와 동일 결과, 소괄호 생략 가능
	oneParam { "Hello World!!! $it" } // 위와 동일 결과, it으로 대체 가능
}
 
// 매개변수가 하나 있는 람다식 함수가 oneParam함수의 매개변수 out으로 지정됨
fun oneParam(out: (String) -> String) {
	println(out("OneParam"))
}

[출력결과]

Hello World! OneParam
Hello World!! OneParam
Hello World!!! OneParam

 

■매개변수가 여러개 있는 경우

fun main() {

	// 매개변수가 두 개 있는 람다식 함수
	moreParam { a, b -> "Hello World! $a $b"} // 매개변수명 생략 불가
}
 
// 매개변수가 두 개 있는 람다식 함수가 moreParam 함수의 매개변수로 지정됨
fun moreParam(out: (String, String) -> String) {
	println(out("OneParam", "TwoParam"))
}

[출력결과]

Hello World! OneParam TwoParam

 

■매개변수를 생략하는 경우 : 언더바(_)를 사용하여 생략한다.

moreParam { _, b -> "Hello World! $b"} // 첫 번째 문자열은 사용하지 않고 생략

 

■일반 매개변수와 람다식 매개변수를 같이 사용하는 경우

fun main() {

	// 인자와 함께 사용하는 경우
	withArgs("Arg1", "Arg2", { a, b -> "Hello World! $a $b" }) // ①
	
    // withArgs()의 마지막 인자가 람다식인 경우 소괄호 바깥으로 분리 가능
	withArgs("Arg1", "Arg2") { a, b -> "Hello World!!! $a $b" } // ②
}

// withArgs함수는 일반 매개변수 2개를 포함, 람다식 함수를 마지막 매개변수로 가짐
fun withArgs(a: String, b: String, out: (String, String) -> String) {
	println(out(a, b))
}

[출력결과]

Hello World! Arg1 Arg2
Hello World!!! Arg1 Arg2

 

■두 개의 람다식을 가진 함수의 사용

fun main() {
	twoLambda({ a, b -> "First $a $b" }, {"Second $it"})
	twoLambda({ a, b -> "First2 $a $b" }) {"Second2 $it"} // 위와 동일
}

fun twoLambda(first: (String, String) -> String, second: (String) -> String) {
	println(first("OneParam", "TwoParam"))
	println(second("OneParam"))
}

[출력결과]

First OneParam TwoParam
Second OneParam
First2 OneParam TwoParam
Second2 OneParam

■람다식에서 return 사용하기

fun main() {
	retFunc()
}

inline fun inlineLambda(a: Int, b: Int, out: (Int, Int) -> Unit) {
	out(a, b)
}

fun retFunc() {
	println("start of retFunc") // ①
	inlineLambda(13, 3) { a, b -> // ②
		val result = a + b
		if(result > 10) return // ③ 10보다 크면 이 함수를 빠져 나감
		println("result: $result") // ④ 10보다 크면 이 문장에 도달하지 못함
	}
	println("end of retFunc") // ⑤
}

[출력결과]

start of retFunc

■람다식에서 라벨과 함께 return 사용하기

람다식 함수명 라벨이름@ {
	...
	retrun@라벨이름
}
fun main() {
	retFunc()
}


fun inlineLambda(a: Int, b: Int, out: (Int, Int) -> Unit) {
	out(a, b)
}

fun retFunc() {
	println("start of retFunc")
	inlineLambda(13, 3) lit@{ a, b -> // ① 람다식 블록의 시작 부분에 라벨을 지정함
		val result = a + b
		if(result > 10) return@lit // ② 라벨을 사용한 블록의 끝부분으로 반환
		println("result: $result")
	} // ③
	println("end of retFunc") // ④ 이 부분이 실행됨
}

[출력결과]

start of retFunc
end of retFunc

 

■람다식에서 라벨과 함께 return 사용하기 :암묵적 라벨 (라벨 생략 가능)

fun retFunc() {
	println("start of retFunc")
	inlineLambda(13, 3) { a, b ->
		val result = a + b
		if(result > 10) return@inlineLambda
		println("result: $result")
	}
	println("end of retFunc")
}

 

[REFERENCE]

Do it! 코틀린 프로그래밍: 03-2 함수형 프로그래밍 :11:00

Do it! 코틀린 프로그래밍: 03-3 고차 함수와 람다식

Do it! 코틀린 프로그래밍: 04-3 흐름의 중단과 반환

 

Leave a Reply

error: Content is protected !!