Pure Function
- 순수 함수
- 같은 input 에 대해서 항상 같은 output 이 나오는 함수
- 외부 상태에 의존적이지 않다.
- 어떠한 Side-effect 도 발생시키지 않는다.
- 쓰레드에 안전하고 병렬적인 계산이 가능하다.
장점
- 테스트가 용이하다.
- 재사용성이 높아진다.
- 예측 가능성이 높아진다.
Side-effect
- 함수형 프로그래밍에서는 잘못된 코드로 인한 오동작의 의미가 아니라 실행 결과 상태의 변화를 일으키는 모든 것을 뜻한다.
var name = "r1verfuture"
func getName() -> String {
return name
}
- [코드 1] : getName 함수는 함수 외부에 있는 'name' 변수에 따라 반환값이 달라진다.
- 이 코드처럼 함수 외부의 값에 의해 함수 반환값이 영향을 받게 되면 Side-effect 가 생길 수 있다. ([코드 1] 은 간단하기 때문에 괜찮아 보일지 몰라도 복잡해지면 괜찮지 않다.)
/ MARK: [코드 2] [코드 1] 을 순수 함수로 변경
var name = "r1verfuture"
func getName(_ name: String) -> String {
return name
}
getName(name)
- [코드 2] : 함수 자체에 파라미터로 받은 name 의 데이터로만 함수 반환값이 결정되기 때문에 함수 외부가 어떻게 달라지든 함수 자체는 전혀 영향을 받지 않고, 파라미터로 전달되는 입력값에 따라서만 영향을 받기 때문에 Side-effect 가 생기지 않는다.
let name = "r1verfuture"
func getName() -> String {
return name
}
- [코드 1] 에서는 'name' 변수가 var (mutable 데이터) 이기 때문에 함수 외부에서 값이 계속 바뀔 수 있지만, [코드 3] 에서는 'name' 변수가 let (immutable 데이터) 이기 때문에 함수 외부에서 값이 바뀔 수 없다. (getName 함수의 출력값이 항상 같다.)
func addTwoValue(_ a: Int, b: Int) -> Int {
return a + b
}
print(addValue(3, b: 5))
- [코드 4] : 외부값에 의해 addTwoValue 함수의 반환값이 달라지는 것이 아니기 때문에 순수 함수가 맞다.
- [코드 4] 를 실행하면 다섯번째 줄에서 8 이 출력된다.
- 입력과 결과가 분리되어 있다.
- 어떻게 사용되는지에 대해 전혀 신경쓰지 않아도 되기 때문에 재사용성이 높아진다.
var c = 10
func addThreeValue(_ a: Int, b: Int, c: Int) -> Int {
return a + b + c
}
print(addValue(3, b: 5, c: c))
c = 20
print(addValue(3, b: 5, c: c))
- [코드 5] : [코드 4] 와 다르게 addThreeValue 의 입력값 중 c 가 외부값에 의해 반환값이 달라지기 때문에 순수 함수가 아니다. (외부에서 c 값을 변경하게 되면 addThreeValue 함수의 반환값이 달라진다.)
- [코드 5] 를 실행하면 7번째줄에서 18 이 출력되지만, 9번째줄에서는 28 이 출력된다.
- [코드 5] 의 첫번째줄에서 'let c = 10' 라고 했을 경우에는 addThreeValue 함수가 외부값을 참조하기는 하지만 순수 함수가 맞다. (c 가 변경 불가능한 상수가 되기 때문이다.)
var c = 20
func addTwoValue2(_ a: Int, b: Int) -> Int {
c = b
return a + b
}
print(c)
print(addTwoValue2(a: 3, b: 5))
print(c)
- [코드 6] 을 실행하면 8번째줄에서 20 이 출력되고, 9번째줄에서 8 이 출력되고, 10번째줄에서 5 가 출력된다.
- [코드 6] : addTwoValue2 함수의 반환값은 항상 같지만 외부의 상태를 변경하는 코드를 가지고 있어서 순수 함수가 아니다.
class ObjectEx {
var num = 10
}
func addTwoValue3(obj: ObjectEx, b: Int) -> Int {
obj.num += b
return obj.num
}
let objEx = ObjectEx()
print(objEx.num)
print(addTwoValue3(obj: objEx, b: 5))
print(objEx.num)
- [코드 7] 을 실행하면 11번째줄에서 10 이 출력되고, 12번째줄에서 15 가 출력되고, 13번째줄에서 15 가 출력된다.
- [코드 7] : 인스턴스를 인자로 받아서 그 인스턴스의 프로퍼티를 변경하는 코드를 가지고 있기 때문에 순수 함수가 될 수 없다. (인스턴스의 프로퍼티 값을 참조하는 식의 코드만 가지고 있어야 한다.)
참고