함수형 프로그래밍

함수형 프로그래밍 정의

데이터의 흐름과 값의 변경에 따라 프로그래밍하지 않고 필요한 로직을
함수로 만들어서 함수들의 흐름에 따라 프로그래밍하자는 개념 입니다.

프로그래밍 패러다임으로서의 함수형 프로그래밍

  1. 절차지향 프로그래밍: 알고리즘과 로직 중심으로 문제 해결이 주목적 예)C,Pascal

  2. 객체지향 프로그래밍: 데이터와 데이터를 처리하는 메서드를 하나로 묶어 객체를 만들고 객체를 조합해서
    프로그래밍 작성, 객체를 만들기위한 추상화, 캡슐화, 상속, 다형성 등의 개념 제공. 예)Java,C++

  3. 함수형 프로그래밍: 함수 선언이 최우선, 데이터의 흐름이 아니라 함수의 선언과 선언된 함수의 유기적인 흐름이 주 목적이다. 예)코틀린,스칼라,스위프트 등

함수형 프로그래밍의 주요 원칙

일급객체(First Class Citizen)로서의 함수

  • 함수가 프로그램의 최상위 구성요소라는 의미입니다. 객체지향 프로그래밍의 경우 함수가 클래스 안에 포함되는 개념으로 클래스가 최상위 단위이며 일급 객체입니다.

  • 함수형 프로그래밍에서는 일급 객체로서 함수를 정의할 수 있어야 합니다. 즉, 클래스를 선언하지 않고도 함수를 정의할 수 있어야 하며, 함수 내에 다양한 구성요소(다른 함수, 클래스)를 포함할 수 있어야 합니다.

  • 어떤 함수의 인수로 변수 대신 함수를 전달할 수 있어야 하고, 함수의 반환값 또한 함수를 반환할 수 있어야 합니다. 즉, 함수를 변수처럼 사용할 수 있어야 하고 이를 함수가 일급객체로 이용된다고 표현 합니다.

순수 함수(Pure Function) 로 정의되는 함수

  • 부수효과(Side-Effect)가 발생하지 않는 함수입니다.

  • 같은 인수를 전달해서 함수를 호출하면 항상 같은 결괏값을 반환한다는 의미 입니다.

  • 이러한 순수 함수가 되려면 함수 내에서 함수 밖의 데이터를 변경하는 작업이 발생하지 않아야 하며, 별도의 입출력이 발생하지 않아야 합니다.

함수형 프로그래밍에서의 데이터 특징

변경할 수 없는 상수 데이터만 이용하고 함수의 흐름에 따라 프로그래밍 하자는 개념

  • 데이터는 변경되지 않으며 프로그램의 상태만 표현한다.(데이터 불변성)

  • 함수에서 데이터는 변경하지 않고 새로운 데이터를 만들어 반환한다.

함수형 프로그래밍의 이점

  • 코드가 간결하여 개발 생산성과 유지 보수성이 증대된다.

  • 동시성 작업을 좀 더 쉽고 안전하게 구현할 수 있다.

코틀린에서 일급 객체로서의 함수

다양한 구성요소를 포함하는 함수

  • 코틀린에서는 함수 자체가 프로그램의 독립적인 구성 단위일 수 있습니다.(함수 내에 다양한 구성요소를 포함)

ex)

fun superFun() {
    val superData = "Hello"

    fun subFun1() {
        println("superData = $superData")
    }

    fun subFun2(a: Int, b: Int): Int {
        subFun1()
        return a + b
    }
    class SubClass{
        fun classFun(){
            println("superData = $superData")
        }
    }
    subFun1()
    SubClass().classFun()
}

변수처럼 이용되는 함수

  • 함수형 프로그래밍에서는 함수가 일급 객체로 이용됩니다. 일급 객체로서의 함수는 함수를 변수처럼 이용할 수 있어야 한다는 개념도 포합됩니다.

  • 코틀린에서 함수를 변수에 대입하려면 람다식으로 표현하거나 함수 참조(Function Reference)를 이용해야 합니다.

  • 함수 참조는 :: 이라는 연산자를 이용하여 함수를 변수에 대입하는 기법 입니다.

val funval = fun someFun() { // 에러

}

val funval1 = { x1: Int ->      // 람다식 이용
    println("hello world")
    x1 * 10
}

funval1(10)

fun someFun() {
    println("i's someFun()")
}

val funval2 = ::someFun         //함수 참조 이용

funval2()

람다 표현식

람다 표현식이란?

함수의 축양형인 람다식, 람다 함수는 익명 함수(Anonymous Function)를 지칭하는 용어 입니다.
많은 프로그래밍 언어에서 코드의 간결함을 주목적으로 자주 이용합니다.

람다 함수 선언 형식

{ 매개변수 -> 함수내용 }

람다 함수 선언의 규칙

  • 람다 함수는 항상 { }으로 감싸서 표현해야 합니다.

  • { } 안에 -> 표시가 있으며 -> 왼쪽으로는 매개변수, 오른쪽으로는 함수 내용입니다.

  • 람다 함수를 정의할 때 매개변수가 없으면 -> 왼쪽을 생략하거나 -> 자체를 생략할 수도 있습니다.

  • 매개변수 타입을 선언해야 하며 추론할 수 있을때는 생략이 가능합니다.

  • 함수의 반환값은 함수 내용의 마지막 표현식이다.

ex)

fun sum(x: Int, y: Int): Int = x + y // 일반적인 함수 정의

val sumVal = { x: Int, y: Int -> x + y }  // 람다 표현식으로 sumVal에 대입

val sumVal2 = { x: Int, y: Int ->
    println("hello")
    x + y                           // 람다함수 내부가 여러줄일때 마지막줄이 리턴값이 된다.
}

val sum1 = { -> 10 + 20 } // 매개변수가 없는 람다
val sum2 = { 10 + 20 }    // 매개변수가 없는 람다

fun main() {
    {x: Int, y: Int -> x+y}(10,20) //람다함수 정의 하고 바로 호출
}

참조 : 깡샘의 코틀린 프로그래밍