함수형 프로그래밍 (fp)

오늘은 함수형 프로그래밍, Functional Programming에 대해서 공부해보려고한다.

함수형 프로그래밍

☝ 함수형 프로그래밍이 뭔데?

함수형 프로그래밍이란, 말 그대로 함수를 기반으로 프로그래밍 하는 방식이다.

함수형 프로그램을 위한 몇 가지 원칙이 있는데, 아래와 같다.

  1. 입출력이 순수해야한다. (=순수함수)
    • 하나 이상의 인자를 받고, 받은 인자를 처리하여 결과물을 내야함.
    • 인자 외의 변수는 사용하면 안됨.
  2. 불변성을 만족해야 한다.
    • 일반적으로 데이터가 바뀌어서는 안됨.
    • 원본 데이터는 불변해야함.
    • 데이터 변경이 필요한 경우, 데이터의 복사본을 이용해 작업한다.
  3. 함수와 데이터를 중점으로 생각해야한다.
  4. 반복문보다는 재귀를 사용한다.

🤞 그걸 하면 뭐가 좋은데?

1. 함수는 입력과, 출력만이 존재한다.

내부적으로 어떤 상태값도 갖지 않는다. 단순히 입력에 따른 출력만을 내뱉는다.

이런 특징은 코드의 테스트를 쉽게 하며, 또한 함수마다 하는 일이 명확하기때문에 코드를 읽기 쉽다.

2. 함수가 값처럼 쓰일 수 있다.

함수가 값처럼 쓰일 수 있기 때문에, 어떤 함수의 입력은 다른 함수가 될 수도 있다.

이런 특징은 함수들의 결합이나 분해, 조합에 있어 매우 용이하다.

🤟 예시

Kotlin

fun pure(numbers: List<Int>) {
    print(numbers.map{it*2})
}

fun main() {
    var numbers = listOf(1, 2, 3, 4, 5)
    pure(numbers)
}

Return

[2, 4, 6, 8, 10]

위의 pure() 함수는 함수형 프로그래밍 함수다!

input을 사용하고, output을 냈으며, 함수 외의 값을 사용하지 않았고, 원본데이터가 변하지도 않았다.

이러한 함수를 순수함수라고 한다.

다른 예시를 보자.

Kotlin

val multiple = 10

fun notPure(numbers: List<Int>) {
    print(numbers.map{it*multiple})
}

fun main() {
    var numbers = listOf(1, 2, 3, 4, 5)
    notPure(numbers)
}

Return

[10, 20, 30, 40, 50]

위의 notPure()함수는 순수함수일까?

이름에서부터 알아봤겠지만, 순수함수가 아니다.

multiple라는 값이 인자가 아님에도 함수 내부에서 호출되었다.

이를 순수 함수로 바꾸기 위해서는, multiple 또한 함수 인자로 받아서 사용하면 된다.

아래는 1부터 10까지 더한 결과를 내는 함수를 각각 반복문과 재귀문을 이용해 작성한 예제다.

Kotlin

fun loopSum(target: Int): Int{
    var sum = 0
    for (i in 1..target) {
        sum += i
    }
    return sum
}

fun recursionSum(sum: Int, now: Int): Int{
    if(now == 0)
    	return sum
    else
	    return recursionSum(sum+now, now-1)
}

fun main() {
    print("Loop: ${loopSum(10)}\n")
    print("Recursion: ${recursionSum(0,10)}")
}

Return

Loop: 55
Recursion: 55

두 함수 모두 같은 값을 출력했으나, 위의 함수는 반복문, 아래 함수는 재귀함수로 구성하였다.

만약 자신이 함수형 프로그래밍을 추종한다면 위의 방법 보다는 아래의 방법으로 함수를 구성하여야 할 것이다.

이런식으로 만들어두면, 함수의 재사용성이 매우 높아진다는 장점이 있다. 언제든 이 함수를 다시 꺼내 쓸 수 있다는 이야기다!

데이터변경을 하지 않는 함수형 프로그래밍의 특성상 기존 데이터를 list.filter, list.map, list.reduce등의 함수를 이용해 복사본을 만들어 연산을 할 수도 있다.

아래는 mapreduce를 이용해 만든 1부터 10까지의 덧셈 연산이다.

Kotlin

fun mapSum(numbers: List<Int>): Int{
    var sum = 0
    numbers.map{sum += it}
    return sum
}

fun reduceSum(numbers: List<Int>): Int{
    var result = numbers.reduce{ sum, number -> sum + number}
    return result
}

fun main() {
    val numbers = listOf(1,2,3,4,5,6,7,8,9,10)
    print("Map: ${mapSum(numbers)}\n")
	print("Reduce: ${reduceSum(numbers)}")
}

Return

Map: 55
Reduce: 55

이러한 함수형 프로그래밍 함수를 이용하여 만든 순수함수들은 재귀문이나 반복문을 이용한 함수보다 더욱 함수형 프로그래밍에 더 인접한 코딩 방식이다.

🍀 마치며

이러한 함수형 프로그래밍은 막 특별하고 새로운 기술이라거나, 그런 거창한 영역은 아닌 것 같다.

기존의 객체지향과는 다른 새로운 관점의 접근 방식이자, 구현 방식이라고 생각한다.

하지만 유지보수나 같이 개발하는 동료들의 입장에서 이런 식으로 직관적으로 코드를 남기는 동료가 있다면 협업에 있어 어려움이 조금이라도 덜어질 것 같다.

내가 먼저 그런 동료가 될 수 있도록 노력해야겠다.

오늘은 여기까지 하고 글 줄이겠다.

쓩!

카테고리:

업데이트:

댓글남기기