순수함수와 일급 객체 함수
- 순수함수(Pure Function)
- 동일한 입력에 대해 항상 동일한 출력을 반환함.
- 오로지 입력 값에만 의존함.
- 외부 상태나 데이터에 의존X
- 함수 실행 중 외부의 상태를 변경하지 않음.
- 함수 내부에서 어떤 부수 효과도 발생시키지 않음.
- 일급 객체 함수(First-Class Function)
- 다음과 같은 특징을 만족함.
- 변수에 할당될 수 있음.
- 함수의 인자로 전달될 수 있음.
- 함수의 결과로 반환될 수 있음.
- 자료 구조에 저장될 수 있음.
- 이러한 특징은 고차 함수(Higher-Order Function)를 쉽게 구현할 수 있음.
부수효과(Side Effect)
- 함수가 실행되는 과정에서 외부 데이터를 사용 및 수정하거나 외부의 다른 기능을 사용하는 것.
- 함수가 전역변수를 사용하거나 수정하는 경우
- I/O 작업
- 객체의 상태를 변경
- 등
// 순수 함수
fun add(a: Int, b: Int): Int = a + b // 동일한 입력에 동일한 출력 반환
// 순수 함수가 아님
var counter = 0
fun increment(): Int {
counter += 1 // side effect
return counter
}
일급 객체 함수 처리
fun main() {
println(add1(10, 20))
println(add2(1, 2))
println(highFunc({ x: Int, y: Int -> x * y }, 100, 100))
val rf = returnFunc()
println(rf(3, 5))
// 일급 함수를 자료구조에 저장
val map = mutableMapOf<String, (Int, Int) -> Int>()
map["add"] = ::add
map["mul"] = ::mul
val operator = "*"
when(operator) {
"+" -> println(map["add"]?.invoke(10, 20))
"*" -> println(map["mul"]?.invoke(10, 20)) // 200
else -> println("없음")
}
}
val add1 = fun (x: Int, y: Int): Int = x + y // 익명 함수 변수에 할당
val add2 = { x: Int, y: Int -> x + y } // 람다를 변수에 할당
fun highFunc(sum: (Int, Int) -> Int, a: Int, b: Int): Int = sum(a, b) // 함수의 인자로 전달
fun returnFunc(): (Int, Int) -> Int = { x: Int, y: Int -> x + y } // 반환 타입을 람다로 반환
fun add(a: Int, b: Int): Int = a + b
fun mul(a: Int, b: Int): Int = a * b
실행결과
30
3
10000
8
200
커링(Currying Function)함수 알아보기
- 여러 개의 인수를 받는 함수를 하나의 인수만을 받는 여러개의 함수로 분해하는 패턴임.
- 함수형 프로그래밍에서 일반적으로 사용되는 기법 중 하나임.
// fun add(x: Int, y: Int): Int = x + y add 함수를 커링함수로 바꿈.
fun main() {
val add2 = addCurried(2)
println(add2)
val result = add2(3)
println(result)
}
fun addCurried(x: Int): (Int) -> Int {
return fun(y: Int): Int {
return x + y
}
}
실행결과
(kotlin.Int) -> kotlin.Int
5
메서드 체인처리
class Person(var name: String, var age: Int) {
fun introduce() { println("Hello, I'm $name and I'm $age years old.") }
fun changeAge(newAge: Int): Person {
this.age = newAge
return this
}
}
// 확장 함수로도 정의 가능
fun Person.changeName(newName: String): Person {
this.name = newName
return this
}
fun main() {
val john = Person("John", 25)
.changeName("Johnny")
.changeAge(26)
.introduce() // 출력: Hello, I'm Johnny and I'm 26 years old.
}
고차 함수
- 함수를 객체로 생각해서 인자로 전달되거나 반환값으로 처리되는 함수.
- 함수의 매개변수에 함수 자료형을 정의하고 함수를 호출할 때 인자로 다른 함수를 받음.
- 함수 내부에서 반환값으로 다른 함수를 반환함.
- 인자와 반환값으로 함수, 익명함수, 람다로 처리할 수 있음.
- 함수일 경우엔 함수 이름이 아닌 함수 참조로 처리해야함.
typealias IntOperation = (Int, Int) -> Int
fun highFunction(vararg x: Int, op: IntOperation): Int = x.toList().reduce(op) // 함수를 매개변수로 받음.
fun add(x: Int, y: Int): Int = x + y
fun returnFunction(): IntOperation = { x, y -> x + y } // 함수 반환
fun main() {
println(highFunction(1, 2, 3, 4, op = { x: Int, y: Int -> x + y })) // 람다 전달
println(highFunction(1, 2, 3, 4, 5, op = ::add)) // 함수 참조 전달
println(returnFunction()(10, 20))
}
실행결과
10
15
30
typealias
는 Kotlin에서 타입에 대한 다른 이름(alias)을 제공하는 방법임.
- 주로 긴 제네릭 타입 표현식의 단순화나 코드의 가독성을 높이기 위해 사용됨.