1. Lamda(람다식)
이름이 없는 함수를 표현하기 위해 등장한 람다식 표현은 함수형 프로그래밍에서 매우 중요한 부분.
람다식은 많은 코드들을 간략화 하고,
함수 자체를 인자나 매개변수로 이용할 수 있다.
fun 함수명(매개변수 명 : () -> 반환타입)
{
}
fun main(args : Array<String>)
{
f1( a1 = { println("함수가 호출되었다")} )
f2(a2 = { x: Int, y: Int ->
println("f2가 전달한 함수가 호출되었다");
println(x);
println(y);
});
f3(a1 = {x:Int, y:Int ->
x+y;
})
}
fun f1( a1 : () -> Unit)
{
a1();
}
fun f2( a2 : (Int, Int) -> Unit)
{
a2(100, 200);
}
// Main함수에서 여기로 전달해주는 매개변수로 이 함수를 실행한다.
fun f3(a1 : (Int, Int) -> Int)
{
var a2 = a1(100, 200);
println(a2);
}
1. 고차 함수의 형태
고차 함수는 인자나 반환값으로 함수를 사용한다.
1. 일반 함수를 인자에 사용하는 경우
fun sum(a : Int, b : Int) = a+b
fun mul(a : Int, b : Int) = a*b
fun main) {
val res1 = sum(3,5) -> 일반 인자
val res2 = sum(mul(3,5), 5) -> 인자에 함수를 사용
}
2. 함수의 반환값으로 일반 함수를 사용하는 경우
fun sum(a : Int, b : Int) = a + b
fun main() {
println( "${highorderFunc()}" )
}
fun highorderFunc() : Int {
return sum(3,5)
}
2. 람다식 매개변수
1. 변수에 할당하는 람다식 함수
fun main() {
var result : Int
val mul : (Int, Int) -> Int = { x : Int , y : Int -> x * y } -> 일반 변수에 람다식 할당
result = mul(10,20) -> 람다식이 할당된 변수는 함수처럼 사용 가능
println(result)
}
2. 람다식 매개변수 mul 자세하게.
val mul : (Int, Int) -> Int = { x : Int, y : Int -> x * y }
(Int, Int) -> Int = 람다식의 자료형 선언
{ x : Int, y : Int } = 람다식의 매개변수
{ -> x * y } = 람다식의 처리 내용
람다식의 매개변수에 자료형이 지정되어 있다면 변수의 자료형은 생략할 수 있다.
val mul : (Int, Int) -> Int = { x:Int, y:Int -> x*y }
val mul = { x: Int, y:Int -> x*y }
val mul : (Int, Int) -> Int = { x,y -> x*y }
셋은 모두 똑같은 뜻
val mul = {x,y -> x*y } (x) 틀린 표현. 자료형을 유추할 수 없음
람다식의 표현식에 여러 표현식이 있다면, 가장 마지막의 표현식이 나오게 된다.
val mul : (Int, Int) -> Int = { println("하히후헤호" x,y -> x*y }
반환 자료형이 아예 없거나 매개변수가 하나만 있을 경우의 람다식 매개변수
1. 반환형이 없는 경우 Unit
val greet : () -> Unit = { println("하히후헤호") }
2. 람다식의 매개변수가 하나만 있을 경우
val square : (Int) -> Int = { x : Int -> x*x }
fun main() {
val out : () -> Unit = {println("helloworld")}
out() // 람다식을 함수처럼 사용 가능
val new = out // 람다식이 들어 있는 변수를 다른 변수에 할당
new()
}
3. 람다식과 고차 함수 호출하기
1. 호출 방법
함수자체를 인자, 매개변수, 반환값으로 사용하려면 변수들의 호출 방법을 이해해야한다.
1. 기본형 변수는 할당된 값은 Stack에 있고 다른 함수에 인자로 전달하는 경우에는 해당 값이 복사되어 전달된다.
2. 참조형 변수로 할당된 객체는 참조 주소가 Stack에 있고 객체는 Heap에 있다. 참조형 객체를 함수에 전달할 때는 참조된 주소가 복사되어 전달된다.
JVM에서 구동되는 JAVA나 Kotlin은 함수를 호출할 때 인자의 값만 복사하는 'Call by Value'가 일반적이다.
C/C++처럼 포인터 주소 연산이 없기 때문에 'Call by Reference'는 사용하지 않는다.
코틀린에서 Call-by-Value는 함수가 다른 함수의 인자로 전달되는 경우 람다식 함수는 값으로 처리되어 그 즉시 람다식 함수가 수행된 후 값을 전달한다.
2. 람다식 사용에서의 값에 의한 호출vs 이름에 의한 호출
1. CallbyValue
fun CallbyValue(b: Boolean) : Boolean {
println("콜바이밸류 함수호출됨")
return b
}
val lamda : () -> Boolean {
println("람다식 함수호출됨")
true
}
fun main() {
val result = CallbyValue(lamda())
println(result)
}
결과
람다식 함수 호출됨
콜바이밸류 함수 호출됨
true
val result = CallbyValue(lamda()) -> 람다식 <<함수>>를 호출함.
2. 이름에 의한 호출
fun CallbyName( b : () -> Unit ) : Boolean {
println("콜바이네임 함수 호출")
return b()
}
fun lamda( b : () -> Unit ) : Boolean {
println("람다식 함수 호출")
true
}
fun main() {
val result = CallbyName(lamda)
println(result)
}
실행 결과
콜바이네임 함수 호출
람다식 함수 호출
true
fun CallbyName( b: () -> Unit )
val result = CallbyName(lamda)
콜바이네임 매개변수가 람다식 형태이고, 람다식을 "함수 형태"가 아닌 "이름"으로 인자 전달했다.
람다식 자체가 매개변수 b에 복사되어 실제로 실행되는 return b() 전까지 람다식은 실행되지 않는다.
return b() 처럼 실제 함수 형태로 호출되야 비로소 람다식이 실행된다.
3. 다른 함수의 참조에 의한 일반 함수 호출 (in 고차함수)
람다식이 아닌 일반 함수를 또 다른 함수의 인자에서 호출하는 고차 함수의 경우.
fun sum(x:Int, y:Int) = x + y
1. 잘못된 경우
fun funParam(x:Int, y:Int, c:(Int, Int) -> Int) : Int {
return c(a,b)
}
funParam(10,20,sum) -> sum은 람다식이 아니므로 잘못된 표현.
2. :: 키워드
sum()과 funParam()는 인자 수와 자료형의 개수가 동일하다.
이런 경우, 2개의 콜론(::) 기호를 함수 이름에 붙여 소괄호와 인자를 생략하고 사용할 수 있다.
funParam(2,3, ::sum)
fun hello(body : (String, String) -> String ) {
println(body("Hello", "World"))
}
fun text(a : String, b: String) = "Hi! $a $b"
hello(::text)
hello( { a, b -> text(a,b) })
hello { a,b -> text(a,b)
셋 다 동일한 결과.
4. 람다식의 매개변수
1. 람다식에 매개변수가 없는 경우
fun noParam( b : () -> Unit ) = Println(b())
-> 매개변수가 없는 람다식이 noParam함수의 매개변수 b으로 지정된다.
fun main() {
noParam({"Hello World"})
noParam{"Hello World"}
}
2. 람다식에 매개변수가 한 개 있는 경우
fun oneParam ( b : String -> String ){
println(b("안녕하세요"))
}
-> 매개 변수가 1개 있는 람다식이 oneParam()함수의 매개변수 b로 지정됨.
fun main() {
oneParam({a -> "hello! $a})
}
oneParam의 인자로 hello!와 oneParam의 문자열 안녕하세요가 붙게됨.
그래서 "hello 안녕하세요" 출력
아 어렵다
3. 람다식의 매개변수가 2개 이상인 경우
fun moreParam( out : (String, String) -> String ) {
println(out("oneParam", "twoParam"))
}
fun main() {
moreParam ( {a,b -> "hello world! $a, $b} )
}
4. 특정 람다식의 매개변수를 사용하고 싶지 않을 경우 이름 대신 _언더스코어로 대체
moreParam{ _,b -> "helloworld $b"}
5. 일반 함수에 2개의 람다식을 만들어보기
fun twoLamda( x: Int, b: Int, first : (String) -> String, second : (String, String) -> String) {
println(first("OneParam", "TwoParam"))
println(second("OneParam"))
}
fun main() {
twoLamda({a,b -> "First $a, $b"}, {"Second $it" })
}
'Deperecated > Kotlin' 카테고리의 다른 글
코틀린 - 중첩 클래스 (0) | 2020.02.05 |
---|---|
코틀린 - 제네릭 (0) | 2020.02.05 |
코틀린 - 클래스 (0) | 2020.02.05 |
코틀린 - 조건문, 분기문, 반복문 (0) | 2020.02.05 |
코틀린 - 기본 (0) | 2020.02.05 |