2018년 let us:Go!
Functional Programming이 뭐하는건가요?라는 제목의 곰튀김님의 발표를 요약한 글입니다.

함수형 프로그래밍을 한문장으로 말하면
Function - 함수를 이용해서
No Side-Effect - 사이드 이펙트 없도록
Declarative Programming - 선언형 프로그래밍을 이용하는 것이다

Function을 사용한다는 것?

기존에는 오브젝트를 쓰고 그것이 가진 메소드를 호출했다.
함수형 프로그래밍은 함수를 먼저 쓰고 그 다음 데이터를 집어넣음.

//non-FP
account.deposit()
user.login()

//FP
deposit(account)
user(User)

No Side Effect?

OOP

Object들로 프로젝트가 구성이되고 오브젝트들의 연관관계로 만들어짐
OOP에서 기능의 최소 단위는 모듈로 연관된 오브젝트로 구성되어있고,오브젝트는 멤버변수와 메소드로 이루어져있다.
메소드가 수행이 될 때는 멤버변수를 사용하게 된다.
그래서 메소드의 수행결과는 멤버변수가 어떤 상태를 가지고있는가에 따라 결과가 달라지게된다.

FP

함수는 인풋과 아웃풋이 있고, 각각의 인풋과 아웃풋이 연결이 되어 하나의 커다란 아웃풋을 만들게 되며 연결되게 됨.
순수 함수는 항상 동일한 인풋에 대해 동일한 아웃풋을 낸다. 그래서 상태를 가지지 않음.
모듈화의 최소단위는 Function 하나임.

OOP와 FP의 차이는 State의 유무.

Imperative vs Declarative ?

명령형 프로그래밍과 선언형 프로그래밍의 차이
명령형 프로그래밍은 어떤 과정을 통하는가- 에 대해 적는다면
선언형 프로그래밍은 어떤 결과를 얻는가- 에 대해 적는다


명령형 프로그래밍을 선언형 프로그래밍으로 리팩토링하기

Fizzbuzz

: 1부터 1000까지 3의 배수일때 fizz, 5의 배수일때 buzz, 3과 5의 배수일 때 fizzbuzz를 출력하는 프로그램

//명령형 프로그래밍 방식 
var i = 1;
while i <= 1000 {
    if i % 3 == 0, i % 5 == 0 {
        print("fizzbuzz")
    } else if i % 3 == 0 {
         print("fizz")
    } else if i % 5 == 0 {
        print("buzz")
    } else {
        print("\(i)"
    }
    i += 1
}

side-effect를 없애기 위해 바깥에 선언된 i를 없앰

(1...100).forEach { i in
    if i % 3 == 0, i % 5 == 0 {
        print("fizzbuzz")
    } else if i % 3 == 0 {
         print("fizz")
    } else if i % 5 == 0 {
        print("buzz")
    } else {
        print("\(i)"
    }
}

fizzbuzz 프린트해주는 부분을 함수로 만듦

let fizz: (Int) -> String = { i in i % 3 == 0 ? "fizz" : "" }
let buzz: (Int) -> String = { i in i % 5 == 0 ? "buzz" : "" }

(1...100).forEach { i in
    let fizzbuzz = fizz(i) + buzz(i)
    let output = fizzbuzz.isEmpty ? "\(i)" : fizzbuzz
    print(output)

명령형으로 쓰여진 부분을 선언형으로 바꿈

let fizz: (Int) -> String = { i in i % 3 == 0 ? "fizz" : "" }
let buzz: (Int) -> String = { i in i % 5 == 0 ? "buzz" : "" }

let fizzbuzz: (Int) -> String = 
    { i in { s in s.isEmpty ? "\(i)" : s }(fizz(i) + buzz(i)) }
let log: (String) -> () = { print($0) }

(1...100).map(fizzbuzz).forEach(log)    //선언형으로 바뀐 구현체 부분 

One more step..

Monad를 이용해 다시 코드 리팩토링
Monad ? 하나로 감쌌다는 개념.
대표적으로 swift의 Optional. (값이 있을수도, 없을수도 있는 상태를 옵셔널이라는 타입 하나로 감쌈)

func + (_ s1: String?, _ s2: String?) -> (String?) {
    if s1 == nil, s2 == nil { return nil }
    if s1 != nil, s2 == nil { return s1 }
    if s1 == nil, s2 != nil { return s2 }
    return s1! + s2!
}

그럼 OOP와 FP 중 무엇을 써야할까?

우리는 이미 OOP를 이용하고 있다. 뷰컨트롤러 자체도 OOP임. 그래서 OOP와 FP를 같이 사용해야 한다.
그럼 FP는 어디서 사용할까? 핵심적인 부분에 사용할 수 있다. FP를 통해 짧고 신뢰성이 높은 코드를 만든다면 전체적인 프로그램의 신뢰성과 재사용성을 높일 수 있다.

그래서 함수형 프로그래밍이 뭐야?

함수를 이용해서 사이드 이펙트 없이, 선언적으로 프로그래밍 하는 것!

참고
https://www.youtube.com/watch?v=HZkqMiwT-5A&feature=youtu.be