안녕하세요 남갯입니다
오늘은 코틀린으로 배우는 함수형 프로그래밍에 대해 포스팅 해보려고합니다.
1.1 함수형 프로그래밍의 특징
함수형 프로그래밍은 데이터 처리의 참조 투명성을 보장하고 상태와 가변데이터 생성을 피하는 프로그래밍의 패러다임.
특징
1. 불변성 (순수함수)
2. 참조 투명성
3. 일급함수
4. 게으른 평가
장점
1. 부수효과가 없는 프로그램을 만들 수 있어 동시형 프로그래밍에 적함
2. 복잡도가 낮아, 간결한 코드 생성 및 모듈성이 높아 유지보수에 좋다.
3. 예측성을 높여서 컴파일러가 효율적으로 실행되는 코드를 만들어준다.
1.2 순수함수한 무엇인가?
간단하게 말하자면 말그대로 함수인것이다. y = f(x) 에서 항상 동일한 x값에 대해서는 동일한 y값의 결과를 내려준다.
즉 항상 동일한 결과가 나오면 이때문에 부수효과가 없다.
var z =10
@Test
fun main() {
println(impureFunction(1,2)) // 13
z = 20
println(impureFunction(1,2)) // 23
}
fun impureFunction(x: Int, y: Int): Int = x + y + z
이 값은 13,23이 출력됩니다.
위의 함수는 위치에 따라 같은값을 넣어도 다른값이 출력된다. 왜냐하면 외부의 값인 z를 참조해서 생성하기 때문이다.
부수효과가 없다
외부 데이터(사용)을 수정하는것을 말한다.
부수효과를 일으키는 예
var z = 10
fun inpureFunctionWithSideEffect(x: Int, y: Int): Int {
z = y
return x + y
}
위의 함수는 동일 입력에 매번 동일한 결과를 돌려주지만, 외부 변수인 z값을 바꾸기 때문에 순수한 함수가 아니다.
1.3 부수효과 없는 프로그램 작성하기
공유변수 수정으로 인한 부수효과
@Test
fun main() {
println(impureFunction(1, 2)) // 13
println(withSideEffect(10,20)) // 30 출력
println(impureFunction(1, 2)) // 23
}
fun impureFunction(x: Int, y: Int): Int = x + y + z
fun withSideEffect(x: Int, y: Int) : Int{
z = y
return x + y
}
사이드 이펙트를 냈기때문에 아래 함수에서 값이 변경된다.
객체의 상태 변경으로 인한 부수효과
data class MutablePerson(var name : String, var age : Int)
data class ImmutablePerson(val name : String, val age : Int)
위의 클래스는 var로 객체의 상태가 변경 가능하지만
아래 immutable한 객체는 상태의 변경이 불가능한 Read Only 상태이다.
함수형 프로그래밍은 이런 부수효과 즉 변경이 가능한 상태에서 변경을 함으로써 발생하는 불필요한 부수효과를 제거하는것이다.
1.4 참조 투명성
참조투명성이란? 프로그램의 변경 없이 어떤 표현식을 값으로 대체할 수 있다는 뜻이다.
1+1 = 2인데, f(x) = y를 반환하면 f(x)는 y로 대체될 수 있다.
var someName : String = "Joe"
fun hello1(){
println("hello $someName")
}
외부의 변수를 참조하고 있기 때문에 참조에 투명하지 않다.
fun hello2(name : String){
println("hello $name")
}
여기서 println만 나눠주면 참조 투명하게 수정이 가능하다.
1.5 일급함수
일급 객체
세가지를 만족하는 객체지향 언어는 일급객체를 지원한다.
1. 객체를 함수의 매개변수로 넘길 수 있다.
2. 객체를 함수의 반환값으로 돌려 줄 수 있다.
3. 객체를 변수나 자료구조에 담을 수 있다.
일급 객체란? 일급 함수란? 두개의 구분.
이부분이라고 적혀있는데,
- 변수나 데이타에 할당 할 수 있어야 한다.
- 객체의 인자로 넘길 수 있어야 한다.
- 객체의 리턴값으로 리턴 할수 있어야 한다.
일급 함수란?
1. 함수를 함수의 매개변수로 넘길 수 있다.
2. 함수를 함수의 반환값으로 돌려 줄 수 있다.
3. 함수를 변수나 자료구조에 담을 수 있다.
일급 함수를 통해 추상화 높이기
fun calculator() {
val fpCalculator = FpCalculator()
println(fpCalculator.calculate({ n1, n2 -> n1 + n2 },3,1))
println(fpCalculator.calculate({ n1, n2 -> n1 - n2 },3,1))
}
class FpCalculator {
fun calculate(calculator: (Int, Int) -> Int, num1: Int, num2: Int): Int {
if (num1 > num2 && 0 != num2) {
return calculator(num1, num2)
} else {
throw IllegalArgumentException()
}
}
}
로직 자체를 추상화 하면서 계산기의 인터페이스와 구현클래스도 모두 없어졌다.
val lazyValue : String by lazy {
println("지연 초기화")
"hello"
}
지연 초기화를 통해 실제 값이 실행되는 시점이 아닌 호출되는 시점에 값을 초기화 한다.
val infiniteValue = generateSequence(0) { it + 5 }
fun test(){
infiniteValue.take(5).forEach { print(it) }
}
'책 > 코틀린으로 배우는 함수형 프로그래밍' 카테고리의 다른 글
[코틀린으로 배우는 함수형 프로그래밍] 4장 고차함수 (0) | 2020.07.09 |
---|---|
[코틀린으로 배우는 함수형 프로그래밍] 3장 재귀 (0) | 2020.06.25 |
[코틀린으로 배우는 함수형 프로그래밍] 2장 코틀린으로 함수형 프로그래밍 시작하기 (0) | 2020.06.15 |