티스토리 뷰
Lambda
// Lambda expression syntax
val sum: (Int, Int) -> Int = { x: Int, y: Int -> x + y }
val sum = { x: Int, y: Int -> x + y }
// Kotlin 규칙에 따르면 함수의 마지막 매개변수가 함수이면 해당 인수로 전달된 람다 표현식을 괄호 외부에 배치할 수 있습니다.
val product = items.fold(1) { acc, e -> acc * e }
// 람다가 해당 호출의 유일한 인수인 경우 괄호를 완전히 생략할 수 있습니다.
run { println("...") }
/*
it: 단일 매개변수의 암시적 이름
람다 식에 매개변수가 하나만 있는 것은 매우 일반적입니다.
컴파일러가 매개변수 없이 서명을 구문 분석할 수 있는 경우 매개변수를 선언할 필요가 없으며 -> 를 생략할 수 있습니다.
*/
ints.filter { it > 0 } // this literal is of type '(it: Int) -> Boolean'
// 람다 식에서 값 반환
ints.filter {
val shouldFilter = it > 0
shouldFilter
}
ints.filter {
val shouldFilter = it > 0
return@filter shouldFilter
}
// 괄호 외부에 람다식을 전달하는것과 함께 LINQ 스타일 코드를 허용 합니다.
strings.filter { it.length == 5 }.sortedBy { it }.map { it.uppercase() }
// 람다 매개변수를 사용하지 않는 경우 이름 대신 밑줄을 배치할 수 있습니다.
map.forEach { _, value -> println("$value!") }
Anonymous functions
// 명시적으로 지정해야 하는 경우 익명 함수 를 사용할 수 있습니다.
fun(x: Int, y: Int): Int = x + y
// 익명 함수는 이름이 생략된다는 점을 제외하고는 일반 함수 선언과 매우 유사합니다.
// 본문은 표현식(위에 표시된 대로) 또는 블록일 수 있습니다.
// 블록 본문이 있는 익명 함수에 대해서는 명시적으로 리턴타입을 지정해야 합니다. 리턴타입이 없는 경우 Unit으로 가정한한다.
fun(x: Int, y: Int): Int {
return x + y
}
// 매개변수와 반환 유형은 컨텍스트에서 유추할 수 있는 경우 매개변수 유형을 생략할 수 있다는 점을 제외하고 일반 함수와 동일한 방식으로 지정됩니다.
ints.filter(fun(item) = item > 0)
Higher-order functions
- 고차 함수는 함수를 매개변수로 취하거나 함수를 반환하는 함수입니다.
- 고차 함수의 좋은 예는 컬렉션에 대한 함수형 프로그래밍 관용구 fold 입니다.
fun <T, R> Collection<T>.fold(
initial: R,
combine: (acc: R, nextElement: T) -> R
): R {
var accumulator: R = initial
for (element: T in this) {
accumulator = combine(accumulator, element)
}
return accumulator
}
//--------------
fun main() {
val items = listOf(1, 2, 3, 4, 5)
// Lambdas are code blocks enclosed in curly braces.
items.fold(0, {
// When a lambda has parameters, they go first, followed by '->'
acc: Int, i: Int ->
//print("acc = $acc, i = $i, ")
val result = acc + i
//println("result = $result")
// The last expression in a lambda is considered the return value:
result
})
// Parameter types in a lambda are optional if they can be inferred:
//val joinedToString = items.fold("Elements:", { acc, i -> acc + " " + i })
// Function references can also be used for higher-order function calls:
val product = items.fold(1, Int::times) // 위의 items가 아니라 Int의 times 타임즈 메소드 이다.
println("joinedToString = $joinedToString")
println("product = $product")
}
Function types
// function types
() -> A // 반환 타입은 생략할 수 없다.
A -> B
A.(B) -> C
(A, B) -> C
((Int, Int) -> Int)? // nullabe function type
(Int) -> ((Int) -> Unit // 괄호를 사용하여 function과 function을 결합할 수 있다.
// type alias를 사용하여 function type의 별칭을 지정할 수 있다.
typealias ClickHandler = (Button, ClickEvent) -> Unit
Instantiating a function type
// lambda expression
{ a, b -> a + b },
// anonymous function
fun(s: String): Int { return s.toIntOrNull() ?: 0 }
// [top-level, local, member] reference or extension function
::isOdd, String::toInt, foo::toString
// [top-level, local, member] reference or extension property
List<Int>::size
// constructor
::Regex
fun main() {
val repeatFun: String.(Int) -> String = { times -> this.repeat(times) }
val twoParameters: (String, Int) -> String = repeatFun // OK
fun runTransformation(f: (String, Int) -> String): String {
return f("hello", 3)
}
val result = runTransformation(repeatFun) // OK
println("result = $result")
}
/*
result = hellohellohello
*/
Invoking a function type instance
fun main() {
val stringPlus: (String, String) -> String = String::plus
val intPlus: Int.(Int) -> Int = Int::plus
println(stringPlus.invoke("<-", "->"))
println(stringPlus("Hello, ", "world!"))
println(intPlus.invoke(1, 1))
println(intPlus(1, 2))
println(2.intPlus(3)) // extension-like call
}
/*
<-->
Hello, world!
2
3
5
*/
Lambda expressions and anonymous functions
/*
람다 식과 익명 함수는 함수 리터럴입니다.
함수 리터럴은 선언되지 않았지만 즉시 표현식으로 전달되는 함수입니다.
함수 max는 두 번째 인수로 함수 값을 취하기 때문에 고차 함수입니다.
두 번째 인수는 함수 리터럴이라고 하는 자체 함수인 표현식으로, 다음 명명된 함수와 동일합니다.
*/
max(strings, { a, b -> a.length < b.length })
// other example
fun compare(a: String, b: String): Boolean = a.length < b.length
Closures
/*
람다 식 또는 익명 함수는 외부 범위에서 선언된 변수를 포함하는 클로저에 액세스할 수 있습니다.
클로저에 캡처된 변수는 람다에서 수정할 수 있습니다.
*/
var sum = 0
ints.filter { it > 0 }.forEach {
sum += it
}
print(sum)
Function literals with receiver
// 수신기가 있는 함수 유형A.(B) -> C 은 특수한 형태의 함수 리터럴로 인스턴스화할 수 있습니다.
// 함수 리터럴의 본문 내에서 호출에 전달된 수신기 개체는 암시적 this 이므로 추가 한정자 없이 해당 수신기 개체의 멤버에 액세스하거나 this를 사용하여 수신기 개체에 액세스할 수 있습니다.
val sum: Int.(Int) -> Int = { other -> plus(other) }
// 익명 함수 구문을 사용하면 함수 리터럴의 수신자 유형을 직접 지정할 수 있습니다. 이것은 수신기를 사용하여 함수 유형의 변수를 선언한 다음 나중에 사용해야 하는 경우에 유용할 수 있습니다.
val sum = fun Int.(other: Int): Int = this + other
'Programming > Kotlin' 카테고리의 다른 글
Kotlin Function (0) | 2022.05.14 |
---|---|
Kotlin Reflection (0) | 2022.04.30 |
Kotlin Generic (0) | 2022.04.30 |
Kotlin Null Safety (0) | 2022.04.23 |
Kotlin Loop (0) | 2022.04.23 |
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
- Total
- Today
- Yesterday
링크
TAG
- Typesafe Config
- Sprint RetryTemplate
- Charles proxy
- Embeddable Mapping
- Registrar
- Spring Registrar
- JPA Criteria
- RetryTemplate
- scikit-learn
- Spring JDBC Template
- java Equals
- spring spel
- JPA
- java EqualsAndHashCode
- Mapping
- docker
- java generic
- 복합키 Mapping
- Akka
- @Primary
- Criteria
- Join Table
- Query DSL
- SmartLifecycle
- Spring
- Embedded Mapping
- Discriminate Mapping
- DI
- Property
- guava
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
글 보관함