Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
Tags
- falsePosition
- SCPC
- 선형분류
- 알고리즘
- 개발순서
- 로지스틱 회귀
- 근구하기
- 인공지능
- 알고리즘대회
- 스터디
- 1차예선
- 2018
- vector미분
- 이것이 MySQL이다
- graphical models
- chapter01
- Perceptron Convergence theorem
- chapter02
- secant
- undirected graphical model
- Fisher discriminant analysis
- Numerical optimization
- MySQL
- directed graphical model
- CH01
- 5397번
- 델타 rule
- 선형판별분석
- bisection
- 자바ORM표준JPA프로그래밍
Archives
- Today
- Total
computer_study
[Kotlin] 05. 고급 함수와 함수형 프로그래밍 활용하기 본문
함수타입
// 함수가 인자를 받지 않는 경우에도 함수 타입의 파라미터 목록에 빈 괄호를 사용해야 한다.
fun measureTime(action: () -> Unit): Long{
...
}
//**********
val succes: (Int) -> Int = {n -> n+1} // ok , 타입을 명시해서 컴파일러가 추론 없이 알 수 있도록 할 수 있다.
val error: Int -> Int = {n -> n+1} // error
호출 가능 참조
존재하는 함수 정의를 함수 타입의 식으로 사용할 수 있는 단순한 방법.
함수 이름 앞에 ::를 붙여서 호출 가능 참조를 할 수 있다.
fun evalAtZero(f: (Int) -> Int) = f(0)
fun inc(n: Int) = n+1
fun dec(n: Int) = n-1
fun main(){
fun dec{n: Int} = n-1
println(evalAtZero(::inc)) // 1
println(evalAtZero(::dec)) // -1
}
// 생성자에도 가능하다
class Person(val firstName: String, val familyName: String)
fun main(){
val createPerson= ::Person
createPerson("John", "Doe")
}
// 클래스 인스턴스의 문맥 안에서 멤버 함수를 호출할 때에는 바인딩된 호출 가능 참조 사용
class Person(val firstName: String, val familyName: String){
fun hasNameOf(name: String) = name.equals(firstName, ignoreCase = true)
}
fun main(){
val isJohn = Person("John", "Doe")::hasNameOf
println(isJohn("JOHN")) // true
println(isJohn("Jake")) // false
}
오버로딩된 함수를 구분하기 위해선 타입을 지정해주어야 한다.
확장함수
- 어떤 클래스의 멤버인 것처럼 호출할 수 있는 함수 (실제 멤버는 아니다)
- 일반 함수를 마치 클래스 멤버인 것처럼 쓸 수 있게 해준다.
- null이 될 수 있는 타입에 대해서도 확장을 정의할 수 있다.
- 클래스 안에서 확장 함수나 프로퍼티를 선언하여 수신 객체가 두 개 있는 것 보단, 최상위 확장을 우선적으로 사용하는 것이 간단하고 읽기 좋은 코드를 만든다.
// util.kt
package util
fun String.truncate(maxLength: Int): String{
return if (length <= maxLength) this else substring(0, maxLength)
}
// main.kt
package main
import util.truncate
fun main(){
println("Hello".truncate(3))
}
확장 프로퍼티
일반 프로퍼티와 마찬가지로 확장 프로퍼티에 접근할 수 있도록 한다.
val IntRange.leftHalf: IntRange
get()=start..(start + endInclusive)/2
fun main(){
println((1..3).leftHalf) // 1..2
println((3..6).leftHalf) // 3..4
}
동반 확장
동반 객체의 성질(클래스에 내포된 객체 중에서 바깥 클래스의 이름을 톨해 객체 멤버에 접근할 수 있다)이 확장의 경우에도 성립한다.
// 확장 클래스
fun IntRange.Companion.singletonRange(n: Int) = n..n
fun main(){
println(IntRange.singletonRange(5)) // 5..5
println(IntRange.Companion.singletonRange(3)) // 3..3 이렇게도 가능
}
// 확장 프로퍼티
val String.Companion.Hello
get() = "Hello"
fun main(){
println(String.HELLO)
println(String.Companion.HELLO)
}
// 람다에도 확장 수신 객체 활용 가능
fun aggregate(number: IntArray, op: Int.(Int) -> Int): Int{ // 수신 객체 타입 정의
var result = numbers.firstOrNull()
?: throw IllegalArgumentException("Empty array")
for(i in 1..numbers.lastIndex) result = result.op(numbers[i])
return result
}
fun sum(numbers: IntArray) = aggregate(numbers) {op -> this + op} // this를 사용해 객체 접근
//익명 함수에도 확장 수신 객체 활용 가능
fun sum(numbers: IntArray) = aggregate(numbers, fun Int.(op: Int)=this + op)
수신 객체가 있는 호출 가능 참조
수신 객체가 있는 함수값을 정의하는 호출 가능 참조를 만들 수 있다.
fun aggregate(number: IntArray, op: Int.(Int) -> Int): Int{
var result = numbers.firstOrNull()
?: throw IllegalArgumentException("Empty array")
for(i in 1..numbers.lastIndex) result = result.op(numbers[i])
return result
}
fun Int.max(other: Int) = if (this > other) this else other
fun main(){
val numbers = intArrayOf(1,2,3,4)
println(aggregate(numbers, Int::plus)) // 10, Int내장 클래스의 멤버함수 사용
println(aggregate(numbers, Int::max)) // 4, 같은 구문을 사용해서 파일에 정의된 확장함수 사용
}
영역함수
- 식을 계산한 값을 임시로 사용할 수 있게 해주거나, 지역변수를 선언하지 않아도 식의 값이 들어있는 암시적인 영역을 정의해서 코드를 단순화 시켜주는 함수
- 인라인 함수이기에 런타임 부가 비용이 없다
- 남용한다면 코드 가독성은 나빠질 수 있다.
- 종류
- run
- 확장 람다를 받는 확장 함수. 람다의 결과를 돌려준다
- 확장 함수로 문맥이 없는 run도 있다
- let
- run과 비슷
- 확장 함수 타입의 람다를 받지 않고 인자가 하나뿐인 함수 타입의 람다를 받는다.
- with
- run과 비슷하며, with는 확장 함수 타입이 아니라 문맥 식을 with의 첫 번째 인자로 전달해야 한다
- apply
- 확장 람다를 받는 확장 함수
- run과 달리 반환값을 만들지 않는다.
- also
- apply와 비슷
- 인자가 하나 이쓴 람다를 파라미터로 받는다는 차이가 있다.
- run
'스터디 > 코틀린 완벽 가이드' 카테고리의 다른 글
[Kotlin] 07. 컬렉션과 I/O 자세히 알아보기 (0) | 2022.06.03 |
---|---|
[Kotlin] 06. 특별한 클래스 사용하기 (0) | 2022.05.27 |
[Kotlin] 03. 함수 정의하기 (0) | 2022.05.19 |
[kotlin] 02. 코틀린 언어 기초 (0) | 2022.05.19 |
[Kotlin] 00.스터디 개요 (0) | 2022.05.18 |
Comments