• [코틀린으로 배우는 함수형 프로그래밍] 함수형 프로그래밍의 특징과 장점
    개발공부/함수형 프로그래밍 2022. 6. 6. 22:35
    반응형

    함수형 프로그래밍이란?

    • 함수를 사용해서 데이터 처리의 참조 투명성을 보장하고, 상태와 가변 데이터 생성을 피하는 프로그래밍 패러다임이다.

     

    함수형 프로그래밍을 사용하는 이유

    • 프로그램이 복잡해질수록 동시성 프로그래밍과 비동기 프로그래밍이 필요한데, 함수형 프로그래밍이 동시성과 비동기에 적합하다.

     

    함수형 프로그래밍의 특징

    1. 참조 투명성 (referential transparency)
    2. 불변성 (immutable)
    3. 일급 함수 (first-class-function)
    4. 게으른 평가 (lazy evaluation)

     

    1. 참조 투명성이란?

    • 프로그램의 변경 없이 어떤 표현식을 값으로 대체할 수 있다.
    fun main() {
        val result = transparent("Joe")
        print(result)
    }
    
    fun transparent(name: String) = "Hello $name" // 참조 투명한 함수
    
    fun print(helloStr: String) { // 부수효과를 일으키는 함수(?)
       println(helloStr)
    }

    위 코드의 transparent() 함수는 아래와 같이 표혁식을 값으로 대체할 수 있다.

    val result = "Hello Joe"

     

    2. 일급 함수란? (객체지향의 일급 객체와 동일)

    • 함수(객체)를 함수의 매개변수로 넘길 수 있다.
    • 함수(객체)를 함수의 반환값으로 돌려 줄 수 있다.
    • 함수(객체)를 변수나 자료구조에 담을 수 있다.

     

    3. 일급 함수를 이용한 추상화와 재사용성

    • 계산기 예제
    fun main() {
        val calculator = SimpleCalculator()
        println(calculator.calculate('+', 3, 1)) // 4
        println(calculator.calculate('-', 3, 1)) // 2
    }
    
    class SimpleCalculator {
       fun calculate(operator: Char, num1: Int, num2: Int): Int = when (operator) {
          '+' -> num1 + num2
          '-' -> num1 - num2
          else -> throw IllegalArgumentException()
       }
    }
    
    // calculate함수가 여러가지 기능을 포함한다. 좋은 코드는 아니다.
    • 객체지향적으로 개선한 계산기 예제
    fun main() {
        val plusCalculator = OopCalculator(Plus())
        println(plusCalculator.calculate(3, 1)) // 4
        
        val minusCalculator = OopCalculator(Minus())
        println(minusCalculator.calculate(3, 1)) // 2
    }
    
    interface Calculator {
       fun calculate(num1: Int, num2: Int): Int
    }
    
    class Plus: Calculator {
       override fun calculate(num1: Int, num2: Int) = (num1 + num2)
    }
    
    class Minus: Calculator {
       override fun calculate(num1: Int, num2: Int) = (num1 - num2)
    }
    
    class OopCalculator {
       fun calculate(operator: Char, num1: Int, num2: Int): Int = Calculator.caculate(num1, num2)
    }
    
    // main이 DI의 주체
    // min 함수가 Calculator 인터페이스를 OopCalculator에 주입한다.
    // OopCalculator는 어떤 계산기가 들어왔는지 알지 못한다.
    // 덧셈과 뺄셈의 비즈니스 로직 분리
    • 함수형 프로그래밍으로 개선한 계산기 예제
    fun main() {
       val fpCalculator = FpCalculator()
       println(fpCalculator.calculate({ n1, n2 -> n1 + n2 }, 3, 1)) // 4
       println(fpCalculator.calculate({ n1, n2 -> n1 - n2 }, 3, 1)) // 2
    }
    
    class FpCalculator {
       fun calculate(
          calculator: (Int, Int) -> Int, 
          num1: Int, 
          num2: Int,
       ): Int = calculator(num1, num2)
    }

    4. lazy evaluation

    • 명령형 프로그래밍 언어는 코드가 실행되면 표현식이 즉시 실행된다. 함수형 언어에서는 표현식이 필요한 시점에 실행되고 프로그래머가 실행 시점을 지정할 수도 있다.

     

    5. 무한대 값을 자료구조에 담다

    fun infiniteValue = generateSequence(0) { it + 5 }
    infiniteValue.take(5).forEach { print("$it ") } // 0 5 10 15 20
    • 명령형 프로그래밍 언어는 코드가 실행되면 표현식이 즉시 실행되기 때문에 무한대를 의미하는 구문이 있다면, 무한 루프에 빠지게 된다. 하지만 함수형 언어에서는 표현식이 필요한 시점에 실행되기 때문에 무한대를 표현하고, 표현식이 실행되는 시점에 take함수로 5개만 출력할 수 있다.

     

     

    일급이 들어가는 단어들 : 일급 객체, 일급 함수, 일급 컬렉션

     

    참고 :

    https://jojoldu.tistory.com/412

    반응형

    댓글

Designed by Tistory.